diff --git a/projects/RPi2/filesystem/usr/lib/modules-load.d/bcm2708-rng.conf b/projects/RPi2/filesystem/usr/lib/modules-load.d/bcm2708-rng.conf
new file mode 100644
index 0000000000..90d50fc6db
--- /dev/null
+++ b/projects/RPi2/filesystem/usr/lib/modules-load.d/bcm2708-rng.conf
@@ -0,0 +1,6 @@
+# /etc/modules-load.d: force some kernel modules to be loaded at boot time.
+#
+# This file contains the names of kernel modules that should be loaded
+# at boot time, one per line. Lines beginning with "#" are ignored.
+
+bcm2708-rng
\ No newline at end of file
diff --git a/projects/RPi2/kodi/advancedsettings.xml b/projects/RPi2/kodi/advancedsettings.xml
new file mode 100644
index 0000000000..e1a7c0dc9b
--- /dev/null
+++ b/projects/RPi2/kodi/advancedsettings.xml
@@ -0,0 +1,20 @@
+
+
+ false
+
+ 720
+ 540
+
+
+
+
+ 30
+
+
+
+ 4.0
+
+
+
diff --git a/projects/RPi2/linux/linux.arm.conf b/projects/RPi2/linux/linux.arm.conf
new file mode 100644
index 0000000000..d0ff3e9f2f
--- /dev/null
+++ b/projects/RPi2/linux/linux.arm.conf
@@ -0,0 +1,3584 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm 3.18.5 Kernel Configuration
+#
+CONFIG_ARM=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_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_FIQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_NEED_MACH_IO_H=y
+CONFIG_NEED_MACH_MEMORY_H=y
+CONFIG_GENERIC_BUG=y
+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="@DISTRONAME@"
+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_HARDIRQS_SW_RESEND=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_HANDLE_DOMAIN_IRQ=y
+# CONFIG_IRQ_DOMAIN_DEBUG is not set
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=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=y
+CONFIG_HIGH_RES_TIMERS=y
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_PREEMPT_RCU=y
+# CONFIG_TASKS_RCU is not set
+CONFIG_RCU_STALL_COMMON=y
+# CONFIG_RCU_USER_QS is not set
+CONFIG_RCU_FANOUT=32
+CONFIG_RCU_FANOUT_LEAF=16
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_RCU_FAST_NO_HZ is not set
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_RCU_BOOST=y
+CONFIG_RCU_BOOST_PRIO=1
+CONFIG_RCU_BOOST_DELAY=500
+CONFIG_RCU_NOCB_CPU=y
+# CONFIG_RCU_NOCB_CPU_NONE is not set
+# CONFIG_RCU_NOCB_CPU_ZERO is not set
+CONFIG_RCU_NOCB_CPU_ALL=y
+CONFIG_BUILD_BIN2C=y
+CONFIG_IKCONFIG=m
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_LOG_CPU_MAX_BUF_SHIFT=12
+CONFIG_GENERIC_SCHED_CLOCK=y
+CONFIG_CGROUPS=y
+# CONFIG_CGROUP_DEBUG is not set
+# CONFIG_CGROUP_FREEZER is not set
+# CONFIG_CGROUP_DEVICE is not set
+# CONFIG_CPUSETS is not set
+# CONFIG_CGROUP_CPUACCT is not set
+# CONFIG_RESOURCE_COUNTERS is not set
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_BLK_CGROUP is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=" "
+CONFIG_INITRAMFS_ROOT_UID=0
+CONFIG_INITRAMFS_ROOT_GID=0
+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 is not set
+# 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_SGETMASK_SYSCALL is not set
+# CONFIG_SYSFS_SYSCALL is not set
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=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 is not set
+CONFIG_ADVISE_SYSCALLS=y
+CONFIG_EMBEDDED=y
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_SLUB_DEBUG=y
+# CONFIG_COMPAT_BRK is not set
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+CONFIG_SLUB_CPU_PARTIAL=y
+# CONFIG_SYSTEM_TRUSTED_KEYRING is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_JUMP_LABEL=y
+# 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_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_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_MODULES_USE_ELF_REL=y
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_OLD_SIGACTION=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=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 is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+# CONFIG_MODULE_COMPRESS is not set
+CONFIG_STOP_MACHINE=y
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+CONFIG_BLK_DEV_BSG=y
+CONFIG_BLK_DEV_BSGLIB=y
+# CONFIG_BLK_DEV_INTEGRITY 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 is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+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 is not set
+# CONFIG_KARMA_PARTITION is not set
+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_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+CONFIG_UNINLINE_SPIN_UNLOCK=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+CONFIG_MUTEX_SPIN_ON_OWNER=y
+CONFIG_RWSEM_SPIN_ON_OWNER=y
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_MULTIPLATFORM is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_BCM2708 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_MSM is not set
+# CONFIG_ARCH_SHMOBILE_LEGACY 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
+CONFIG_ARCH_BCM2709=y
+CONFIG_BCM2708_GPIO=y
+CONFIG_BCM2708_VCMEM=y
+CONFIG_BCM2708_NOL2CACHE=y
+CONFIG_BCM2708_SPIDEV=y
+
+#
+# Broadcom BCM2709 Implementations
+#
+CONFIG_MACH_BCM2709=y
+CONFIG_BCM2709_DT=y
+
+#
+# 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_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_KUSER_HELPERS=y
+CONFIG_MIGHT_HAVE_CACHE_L2X0=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_ARM_L1_CACHE_SHIFT_6=y
+CONFIG_ARM_L1_CACHE_SHIFT=6
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+CONFIG_ARCH_HAS_BARRIERS=y
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_458693 is not set
+# CONFIG_ARM_ERRATA_460075 is not set
+# CONFIG_ARM_ERRATA_742230 is not set
+# CONFIG_ARM_ERRATA_742231 is not set
+# CONFIG_ARM_ERRATA_643719 is not set
+# CONFIG_ARM_ERRATA_720789 is not set
+# CONFIG_ARM_ERRATA_743622 is not set
+# CONFIG_ARM_ERRATA_751472 is not set
+# CONFIG_ARM_ERRATA_754322 is not set
+# CONFIG_ARM_ERRATA_754327 is not set
+# CONFIG_ARM_ERRATA_764369 is not set
+# CONFIG_ARM_ERRATA_775420 is not set
+# CONFIG_ARM_ERRATA_798181 is not set
+# CONFIG_ARM_ERRATA_773022 is not set
+
+#
+# Bus support
+#
+CONFIG_ARM_AMBA=y
+# CONFIG_PCI_SYSCALL is not set
+# 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_ARCH_TIMER=y
+# CONFIG_MCPM is not set
+# CONFIG_BIG_LITTLE is not set
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_NR_CPUS=4
+# CONFIG_HOTPLUG_CPU is not set
+# CONFIG_ARM_PSCI is not set
+CONFIG_ARCH_NR_GPIO=0
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+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 is not set
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+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_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_CLEANCACHE=y
+CONFIG_FRONTSWAP=y
+CONFIG_CMA=y
+# CONFIG_CMA_DEBUG 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_FORCE_MAX_ZONEORDER=11
+CONFIG_ALIGNMENT_TRAP=y
+CONFIG_UACCESS_WITH_MEMCPY=y
+# 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=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+# CONFIG_ARM_APPENDED_DTB is not set
+CONFIG_CMDLINE="root=/dev/ram0 rdinit=/init BOOT_IMAGE=/kernel.img usbcore.autosuspend=-1"
+# CONFIG_CMDLINE_FROM_BOOTLOADER is not set
+CONFIG_CMDLINE_EXTEND=y
+# CONFIG_CMDLINE_FORCE is not set
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_CRASH_DUMP is not set
+# CONFIG_AUTO_ZRELADDR is not set
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_COMMON=y
+# CONFIG_CPU_FREQ_STAT is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+# 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 is not set
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+# CONFIG_CPUFREQ_DT is not set
+
+#
+# ARM CPU frequency scaling drivers
+#
+# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set
+CONFIG_ARM_BCM2835_CPUFREQ=y
+
+#
+# CPU Idle
+#
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+
+#
+# ARM CPU Idle Drivers
+#
+# 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 is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+
+#
+# Power management options
+#
+# CONFIG_SUSPEND is not set
+# CONFIG_HIBERNATION is not set
+# CONFIG_PM_RUNTIME is not set
+CONFIG_CPU_PM=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_ARM_CPU_SUSPEND is not set
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+# CONFIG_XFRM_USER is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+CONFIG_NET_IP_TUNNEL=m
+CONFIG_IP_MROUTE=y
+# CONFIG_IP_PIMSM_V1 is not set
+# CONFIG_IP_PIMSM_V2 is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_NET_UDP_TUNNEL is not set
+# CONFIG_NET_FOU is not set
+# CONFIG_GENEVE is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+CONFIG_INET_LRO=y
+# CONFIG_INET_DIAG is not set
+# 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=y
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_BEET is not set
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_GRE is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NET_PTP_CLASSIFY is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+# CONFIG_BRIDGE_NETFILTER is not set
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+# CONFIG_NETFILTER_NETLINK_ACCT is not set
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK=m
+# CONFIG_NF_CONNTRACK_MARK is not set
+# CONFIG_NF_CONNTRACK_PROCFS is not set
+# CONFIG_NF_CONNTRACK_EVENTS is not set
+# CONFIG_NF_CONNTRACK_TIMEOUT is not set
+# CONFIG_NF_CONNTRACK_TIMESTAMP is not set
+# CONFIG_NF_CT_PROTO_DCCP is not set
+# CONFIG_NF_CT_PROTO_SCTP is not set
+# CONFIG_NF_CT_PROTO_UDPLITE is not set
+# CONFIG_NF_CONNTRACK_AMANDA is not set
+CONFIG_NF_CONNTRACK_FTP=m
+# CONFIG_NF_CONNTRACK_H323 is not set
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_BROADCAST=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+# CONFIG_NF_CONNTRACK_SNMP is not set
+# CONFIG_NF_CONNTRACK_PPTP is not set
+# CONFIG_NF_CONNTRACK_SANE is not set
+CONFIG_NF_CONNTRACK_SIP=m
+# CONFIG_NF_CONNTRACK_TFTP is not set
+CONFIG_NF_CT_NETLINK=m
+# CONFIG_NF_CT_NETLINK_TIMEOUT is not set
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+# CONFIG_NF_NAT_AMANDA is not set
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_SIP=m
+# CONFIG_NF_NAT_TFTP is not set
+# CONFIG_NF_TABLES is not set
+CONFIG_NETFILTER_XTABLES=m
+
+#
+# Xtables combined modules
+#
+# CONFIG_NETFILTER_XT_MARK is not set
+# CONFIG_NETFILTER_XT_CONNMARK is not set
+
+#
+# Xtables targets
+#
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set
+# CONFIG_NETFILTER_XT_TARGET_HMARK is not set
+# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set
+# CONFIG_NETFILTER_XT_TARGET_LED is not set
+# CONFIG_NETFILTER_XT_TARGET_LOG is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+CONFIG_NETFILTER_XT_NAT=m
+# CONFIG_NETFILTER_XT_TARGET_NETMAP is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
+# CONFIG_NETFILTER_XT_TARGET_REDIRECT is not set
+# CONFIG_NETFILTER_XT_TARGET_TEE is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+
+#
+# Xtables matches
+#
+# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_BPF is not set
+# CONFIG_NETFILTER_XT_MATCH_CGROUP is not set
+# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNLABEL is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNLIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNMARK is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNTRACK is not set
+# CONFIG_NETFILTER_XT_MATCH_CPU is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ECN is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_HELPER is not set
+# CONFIG_NETFILTER_XT_MATCH_HL is not set
+# CONFIG_NETFILTER_XT_MATCH_IPCOMP is not set
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+# CONFIG_NETFILTER_XT_MATCH_L2TP is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set
+# CONFIG_NETFILTER_XT_MATCH_OSF is not set
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+# CONFIG_NETFILTER_XT_MATCH_SOCKET is not set
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_TIME is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# CONFIG_IP_SET is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_CONNTRACK_IPV4=m
+# CONFIG_NF_LOG_ARP is not set
+# CONFIG_NF_LOG_IPV4 is not set
+CONFIG_NF_REJECT_IPV4=m
+CONFIG_NF_NAT_IPV4=m
+CONFIG_NF_NAT_MASQUERADE_IPV4=m
+# CONFIG_NF_NAT_PPTP is not set
+# CONFIG_NF_NAT_H323 is not set
+CONFIG_IP_NF_IPTABLES=m
+# CONFIG_IP_NF_MATCH_AH is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+# CONFIG_IP_NF_TARGET_SYNPROXY is not set
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+# CONFIG_IP_NF_TARGET_NETMAP is not set
+# CONFIG_IP_NF_TARGET_REDIRECT is not set
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_RAW is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV6=m
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_NF_REJECT_IPV6=m
+# CONFIG_NF_LOG_IPV6 is not set
+CONFIG_NF_NAT_IPV6=m
+# CONFIG_NF_NAT_MASQUERADE_IPV6 is not set
+CONFIG_IP6_NF_IPTABLES=m
+# CONFIG_IP6_NF_MATCH_AH is not set
+# CONFIG_IP6_NF_MATCH_EUI64 is not set
+# CONFIG_IP6_NF_MATCH_FRAG is not set
+# CONFIG_IP6_NF_MATCH_OPTS is not set
+# CONFIG_IP6_NF_MATCH_HL is not set
+# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set
+# CONFIG_IP6_NF_MATCH_MH is not set
+# CONFIG_IP6_NF_MATCH_RT is not set
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+# CONFIG_IP6_NF_TARGET_SYNPROXY is not set
+# CONFIG_IP6_NF_MANGLE is not set
+# CONFIG_IP6_NF_RAW is not set
+CONFIG_IP6_NF_NAT=m
+# CONFIG_IP6_NF_TARGET_MASQUERADE is not set
+# CONFIG_IP6_NF_TARGET_NPT is not set
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+CONFIG_STP=m
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_IGMP_SNOOPING=y
+# CONFIG_BRIDGE_VLAN_FILTERING is not set
+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 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# 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 is not set
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_MMAP is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_NET_MPLS_GSO is not set
+# CONFIG_HSR is not set
+CONFIG_RPS=y
+CONFIG_RFS_ACCEL=y
+CONFIG_XPS=y
+# CONFIG_CGROUP_NET_PRIO is not set
+# CONFIG_CGROUP_NET_CLASSID is not set
+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_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+CONFIG_BT=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+# CONFIG_BT_BNEP is not set
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIBTUSB=m
+# CONFIG_BT_HCIBTSDIO is not set
+# CONFIG_BT_HCIUART is not set
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+# CONFIG_BT_HCIVHCI is not set
+# CONFIG_BT_MRVL is not set
+CONFIG_BT_ATH3K=m
+# CONFIG_AF_RXRPC is not set
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=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=y
+# CONFIG_CFG80211_DEBUGFS is not set
+CONFIG_CFG80211_INTERNAL_REGDB=y
+CONFIG_CFG80211_WEXT=y
+# CONFIG_LIB80211 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_DEFAULT_MINSTREL=y
+CONFIG_MAC80211_RC_DEFAULT="minstrel_ht"
+# CONFIG_MAC80211_MESH is not set
+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_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+CONFIG_HAVE_BPF_JIT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_UEVENT_HELPER is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
+# CONFIG_ALLOW_DEV_COREDUMP is not set
+# 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_REGMAP=y
+CONFIG_REGMAP_I2C=m
+CONFIG_REGMAP_SPI=m
+CONFIG_REGMAP_MMIO=m
+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=5
+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_BRCMSTB_GISB_ARB is not set
+# CONFIG_ARM_CCI is not set
+# CONFIG_VEXPRESS_CONFIG is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+CONFIG_DTC=y
+CONFIG_OF=y
+
+#
+# Device Tree and Open Firmware support
+#
+# CONFIG_OF_SELFTEST is not set
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_NET=y
+CONFIG_OF_MDIO=y
+CONFIG_OF_RESERVED_MEM=y
+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_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=0
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_DRBD is not set
+CONFIG_BLK_DEV_NBD=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MG_DISK is not set
+# CONFIG_BLK_DEV_RBD is not set
+
+#
+# Misc devices
+#
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES 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 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+CONFIG_EEPROM_93CX6=m
+# CONFIG_EEPROM_93XX46 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+CONFIG_BCM2708_VCHIQ=y
+
+#
+# Intel MIC Bus Driver
+#
+
+#
+# Intel MIC Host Driver
+#
+
+#
+# Intel MIC Card Driver
+#
+# CONFIG_ECHO is not set
+# CONFIG_CXL_BASE 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 is not set
+# CONFIG_SCSI_MQ_DEFAULT is not set
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# 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 is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+CONFIG_SCSI_ISCSI_ATTRS=y
+# 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=y
+CONFIG_ISCSI_BOOT_SYSFS=y
+# CONFIG_SCSI_UFSHCD is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_TARGET_CORE is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_VXLAN is not set
+CONFIG_NETCONSOLE=y
+CONFIG_NETPOLL=y
+CONFIG_NET_POLL_CONTROLLER=y
+CONFIG_TUN=y
+# CONFIG_VETH is not set
+# CONFIG_NLMON is not set
+
+#
+# CAIF transport drivers
+#
+
+#
+# Distributed Switch Architecture drivers
+#
+# CONFIG_NET_DSA_MV88E6XXX is not set
+# CONFIG_NET_DSA_MV88E6060 is not set
+# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set
+# CONFIG_NET_DSA_MV88E6131 is not set
+# CONFIG_NET_DSA_MV88E6123_61_65 is not set
+# CONFIG_NET_DSA_MV88E6171 is not set
+# CONFIG_NET_DSA_BCM_SF2 is not set
+# CONFIG_ETHERNET is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_AT803X_PHY is not set
+# CONFIG_AMD_PHY is not set
+# CONFIG_AMD_XGBE_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_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_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+# CONFIG_MDIO_BUS_MUX_GPIO is not set
+# CONFIG_MDIO_BUS_MUX_MMIOREG is not set
+# CONFIG_MDIO_BCM_UNIMAC is not set
+# CONFIG_MICREL_KS8995MA is not set
+CONFIG_PPP=y
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_MPPE=m
+# CONFIG_PPP_MULTILINK is not set
+CONFIG_PPPOE=m
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=y
+CONFIG_USB_NET_DRIVERS=y
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+CONFIG_USB_RTL8152=m
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_AX88179_178A=m
+CONFIG_USB_NET_CDCETHER=m
+# CONFIG_USB_NET_CDC_EEM is not set
+# CONFIG_USB_NET_CDC_NCM is not set
+# CONFIG_USB_NET_HUAWEI_CDC_NCM is not set
+# CONFIG_USB_NET_CDC_MBIM is not set
+CONFIG_USB_NET_DM9601=y
+# CONFIG_USB_NET_SR9700 is not set
+# CONFIG_USB_NET_SR9800 is not set
+CONFIG_USB_NET_SMSC75XX=m
+CONFIG_USB_NET_SMSC95XX=y
+# CONFIG_USB_NET_GL620A is not set
+# CONFIG_USB_NET_NET1080 is not set
+# CONFIG_USB_NET_PLUSB is not set
+CONFIG_USB_NET_MCS7830=m
+CONFIG_USB_NET_RNDIS_HOST=m
+# CONFIG_USB_NET_CDC_SUBSET is not set
+# CONFIG_USB_NET_ZAURUS is not set
+# CONFIG_USB_NET_CX82310_ETH is not set
+# CONFIG_USB_NET_KALMIA is not set
+# CONFIG_USB_NET_QMI_WWAN is not set
+# CONFIG_USB_NET_INT51X1 is not set
+# CONFIG_USB_IPHETH is not set
+# CONFIG_USB_SIERRA_NET is not set
+# CONFIG_USB_VL600 is not set
+CONFIG_WLAN=y
+# CONFIG_LIBERTAS_THINFIRM is not set
+# CONFIG_AT76C50X_USB is not set
+CONFIG_USB_ZD1201=m
+CONFIG_USB_NET_RNDIS_WLAN=m
+CONFIG_RTL8187=m
+CONFIG_RTL8187_LEDS=y
+# CONFIG_MAC80211_HWSIM is not set
+CONFIG_ATH_COMMON=m
+CONFIG_ATH_CARDS=m
+# CONFIG_ATH_DEBUG is not set
+CONFIG_ATH9K_HW=m
+CONFIG_ATH9K_COMMON=m
+CONFIG_ATH9K_BTCOEX_SUPPORT=y
+CONFIG_ATH9K=m
+CONFIG_ATH9K_AHB=y
+# CONFIG_ATH9K_DEBUGFS is not set
+# CONFIG_ATH9K_DYNACK is not set
+# CONFIG_ATH9K_CHANNEL_CONTEXT is not set
+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 is not set
+CONFIG_ATH6KL_USB=m
+# CONFIG_ATH6KL_DEBUG is not set
+CONFIG_AR5523=m
+# CONFIG_ATH10K 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_SDIO is not set
+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 is not set
+CONFIG_BRCMUTIL=m
+# CONFIG_BRCMSMAC is not set
+CONFIG_BRCMFMAC=m
+CONFIG_BRCMFMAC_PROTO_BCDC=y
+# CONFIG_BRCMFMAC_SDIO is not set
+CONFIG_BRCMFMAC_USB=y
+# CONFIG_BRCM_TRACING is not set
+# CONFIG_BRCMDBG is not set
+# CONFIG_HOSTAP is not set
+# CONFIG_LIBERTAS is not set
+CONFIG_P54_COMMON=m
+CONFIG_P54_USB=m
+# CONFIG_P54_SPI is not set
+CONFIG_P54_LEDS=y
+CONFIG_RT2X00=m
+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_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_RTL_CARDS=m
+# CONFIG_RTL8192CU is not set
+# CONFIG_WL_TI is not set
+CONFIG_ZD1211RW=m
+# CONFIG_ZD1211RW_DEBUG is not set
+# CONFIG_MWIFIEX is not set
+# CONFIG_CW1200 is not set
+# CONFIG_RSI_91X is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=y
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=y
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_JOYSTICK=y
+# CONFIG_JOYSTICK_ANALOG is not set
+# CONFIG_JOYSTICK_A3D is not set
+# CONFIG_JOYSTICK_ADI is not set
+# CONFIG_JOYSTICK_COBRA is not set
+# CONFIG_JOYSTICK_GF2K is not set
+# CONFIG_JOYSTICK_GRIP is not set
+# CONFIG_JOYSTICK_GRIP_MP is not set
+# CONFIG_JOYSTICK_GUILLEMOT is not set
+# CONFIG_JOYSTICK_INTERACT is not set
+# CONFIG_JOYSTICK_SIDEWINDER is not set
+# CONFIG_JOYSTICK_TMDC is not set
+# CONFIG_JOYSTICK_IFORCE is not set
+# CONFIG_JOYSTICK_WARRIOR is not set
+# CONFIG_JOYSTICK_MAGELLAN is not set
+# CONFIG_JOYSTICK_SPACEORB is not set
+# CONFIG_JOYSTICK_SPACEBALL is not set
+# CONFIG_JOYSTICK_STINGER is not set
+# CONFIG_JOYSTICK_TWIDJOY is not set
+# CONFIG_JOYSTICK_ZHENHUA is not set
+# CONFIG_JOYSTICK_AS5011 is not set
+# CONFIG_JOYSTICK_JOYDUMP is not set
+CONFIG_JOYSTICK_XPAD=m
+CONFIG_JOYSTICK_XPAD_FF=y
+CONFIG_JOYSTICK_XPAD_LEDS=y
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_AD714X is not set
+# CONFIG_INPUT_ARIZONA_HAPTICS is not set
+# CONFIG_INPUT_BMA150 is not set
+# CONFIG_INPUT_MMA8450 is not set
+# CONFIG_INPUT_MPU3050 is not set
+# CONFIG_INPUT_GP2A is not set
+# CONFIG_INPUT_GPIO_BEEPER is not set
+# CONFIG_INPUT_GPIO_TILT_POLLED is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_KXTJ9 is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_UINPUT=y
+# CONFIG_INPUT_PCF8574 is not set
+# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
+# CONFIG_INPUT_ADXL34X is not set
+# CONFIG_INPUT_IMS_PCU is not set
+# CONFIG_INPUT_CMA3000 is not set
+# CONFIG_INPUT_DRV260X_HAPTICS is not set
+# CONFIG_INPUT_DRV2667_HAPTICS is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+# CONFIG_DEVKMEM is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_EARLYCON=y
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_AMBA_PL010 is not set
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX310X is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_SC16IS7XX is not set
+# 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 is not set
+# CONFIG_SERIAL_FSL_LPUART is not set
+# CONFIG_SERIAL_ST_ASC is not set
+# CONFIG_TTY_PRINTK is not set
+# CONFIG_HVC_DCC is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+CONFIG_HW_RANDOM_BCM2708=m
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_BRCM_CHAR_DRIVERS=y
+CONFIG_BCM_VC_CMA=y
+# CONFIG_BCM_VC_SM is not set
+# CONFIG_XILLYBUS is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MUX=m
+
+#
+# Multiplexer I2C Chip support
+#
+# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set
+# CONFIG_I2C_MUX_GPIO is not set
+# CONFIG_I2C_MUX_PCA9541 is not set
+# CONFIG_I2C_MUX_PCA954x is not set
+# CONFIG_I2C_MUX_PINCTRL is not set
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_ALGOBIT=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_BCM2835 is not set
+CONFIG_I2C_BCM2708=y
+CONFIG_I2C_BCM2708_BAUDRATE=100000
+# CONFIG_I2C_CBUS_GPIO is not set
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
+CONFIG_I2C_GPIO=y
+# CONFIG_I2C_NOMADIK is not set
+# CONFIG_I2C_OCORES is not set
+# 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_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_BCM2835 is not set
+CONFIG_SPI_BCM2708=y
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_CADENCE is not set
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_FSL_SPI is not set
+# CONFIG_SPI_OC_TINY is not set
+# CONFIG_SPI_PL022 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_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 is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+CONFIG_PINCTRL=y
+
+#
+# Pin controllers
+#
+CONFIG_PINMUX=y
+CONFIG_PINCONF=y
+# CONFIG_DEBUG_PINCTRL is not set
+CONFIG_PINCTRL_BCM2835=y
+# CONFIG_PINCTRL_SINGLE is not set
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_DEVRES=y
+CONFIG_OF_GPIO=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO drivers:
+#
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+# CONFIG_GPIO_DWAPB is not set
+# CONFIG_GPIO_EM is not set
+# CONFIG_GPIO_ZEVIO is not set
+# CONFIG_GPIO_PL061 is not set
+# CONFIG_GPIO_SCH311X is not set
+# CONFIG_GPIO_GRGPIO is not set
+
+#
+# I2C GPIO expanders:
+#
+CONFIG_GPIO_ARIZONA=m
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
+# CONFIG_GPIO_ADP5588 is not set
+# CONFIG_GPIO_ADNP is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_74X164 is not set
+
+#
+# AC97 GPIO expanders:
+#
+
+#
+# LPC GPIO expanders:
+#
+
+#
+# MODULbus GPIO expanders:
+#
+
+#
+# USB GPIO expanders:
+#
+# CONFIG_W1 is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_TEST_POWER 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_BQ27x00 is not set
+# CONFIG_BATTERY_MAX17040 is not set
+# CONFIG_BATTERY_MAX17042 is not set
+# CONFIG_CHARGER_MAX8903 is not set
+# CONFIG_CHARGER_LP8727 is not set
+# CONFIG_CHARGER_GPIO is not set
+# CONFIG_CHARGER_BQ2415X is not set
+# CONFIG_CHARGER_BQ24190 is not set
+# CONFIG_CHARGER_BQ24735 is not set
+# CONFIG_CHARGER_SMB347 is not set
+# CONFIG_POWER_RESET is not set
+# CONFIG_POWER_AVS is not set
+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_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# 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_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 is not set
+# CONFIG_SENSORS_MAX16065 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX1668 is not set
+# 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_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_PCF8591 is not set
+# CONFIG_PMBUS is not set
+# CONFIG_SENSORS_SHT15 is not set
+# CONFIG_SENSORS_SHT21 is not set
+# CONFIG_SENSORS_SHTC1 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_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_VT1211 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_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_GOV_FAIR_SHARE is not set
+CONFIG_THERMAL_GOV_STEP_WISE=y
+# CONFIG_THERMAL_GOV_BANG_BANG is not set
+# CONFIG_THERMAL_GOV_USER_SPACE is not set
+# CONFIG_CPU_THERMAL is not set
+# CONFIG_THERMAL_EMULATION is not set
+CONFIG_THERMAL_BCM2835=y
+
+#
+# Texas Instruments thermal drivers
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_CORE is not set
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_GPIO_WATCHDOG is not set
+# CONFIG_XILINX_WATCHDOG is not set
+# CONFIG_ARM_SP805_WATCHDOG is not set
+# CONFIG_CADENCE_WATCHDOG is not set
+# CONFIG_DW_WATCHDOG is not set
+# CONFIG_MAX63XX_WATCHDOG is not set
+CONFIG_BCM2708_WDT=m
+# CONFIG_MEN_A21_WDT is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB=m
+CONFIG_SSB_BLOCKIO=y
+CONFIG_SSB_SDIOHOST_POSSIBLE=y
+# CONFIG_SSB_SDIOHOST is not set
+# CONFIG_SSB_SILENT is not set
+# CONFIG_SSB_DEBUG is not set
+# CONFIG_SSB_DRIVER_GPIO is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+CONFIG_BCMA=m
+CONFIG_BCMA_BLOCKIO=y
+# CONFIG_BCMA_HOST_SOC is not set
+CONFIG_BCMA_DRIVER_GMAC_CMN=y
+# 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_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_MFD_DA9052_SPI is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_MFD_DA9055 is not set
+# CONFIG_MFD_DA9063 is not set
+# CONFIG_MFD_MC13XXX_SPI is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# 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_INTEL_SOC_PMIC 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_MAX8907 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 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_RTSX_USB=y
+# 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 is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_SMSC is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_STMPE is not set
+# CONFIG_MFD_SYSCON is not set
+# 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 is not set
+# 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_ARIZONA=y
+CONFIG_MFD_ARIZONA_I2C=m
+CONFIG_MFD_ARIZONA_SPI=m
+CONFIG_MFD_WM5102=y
+# CONFIG_MFD_WM5110 is not set
+# CONFIG_MFD_WM8997 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_REGULATOR is not set
+CONFIG_MEDIA_SUPPORT=m
+
+#
+# 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 is not set
+CONFIG_MEDIA_RC_SUPPORT=y
+# CONFIG_MEDIA_CONTROLLER is not set
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2=m
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_VMALLOC=m
+CONFIG_VIDEOBUF_DVB=m
+CONFIG_VIDEOBUF2_CORE=m
+CONFIG_VIDEOBUF2_MEMOPS=m
+CONFIG_VIDEOBUF2_VMALLOC=m
+CONFIG_DVB_CORE=m
+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=m
+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=m
+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 is not set
+CONFIG_IR_IMON=m
+CONFIG_IR_MCEUSB=m
+CONFIG_IR_REDRAT3=m
+CONFIG_IR_STREAMZAP=m
+CONFIG_IR_IGUANA=m
+CONFIG_IR_TTUSBIR=m
+# CONFIG_IR_IMG is not set
+# CONFIG_RC_LOOPBACK is not set
+CONFIG_IR_GPIO_CIR=m
+CONFIG_MEDIA_USB_SUPPORT=y
+
+#
+# Webcam devices
+#
+# CONFIG_USB_VIDEO_CLASS is not set
+# CONFIG_USB_GSPCA is not set
+# CONFIG_USB_PWC is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_USB_ZR364XX is not set
+# CONFIG_USB_STKWEBCAM is not set
+# CONFIG_USB_S2255 is not set
+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 is not set
+# CONFIG_VIDEO_TLG2300 is not set
+# CONFIG_VIDEO_USBVISION is not set
+CONFIG_VIDEO_STK1160_COMMON=m
+# CONFIG_VIDEO_STK1160_AC97 is not set
+CONFIG_VIDEO_STK1160=m
+# CONFIG_VIDEO_GO7007 is not set
+
+#
+# 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 is not set
+CONFIG_VIDEO_CX231XX_DVB=m
+CONFIG_VIDEO_TM6000=m
+# CONFIG_VIDEO_TM6000_ALSA is not set
+CONFIG_VIDEO_TM6000_DVB=m
+
+#
+# Digital TV USB devices
+#
+CONFIG_DVB_USB=m
+# CONFIG_DVB_USB_DEBUG is not set
+# CONFIG_DVB_USB_A800 is not set
+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 is not set
+CONFIG_DVB_USB_CXUSB=m
+# CONFIG_DVB_USB_M920X is not set
+# CONFIG_DVB_USB_DIGITV is not set
+CONFIG_DVB_USB_VP7045=m
+# CONFIG_DVB_USB_VP702X is not set
+# CONFIG_DVB_USB_GP8PSK is not set
+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 is not set
+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 is not set
+CONFIG_DVB_USB_AZ6007=m
+CONFIG_DVB_USB_CE6230=m
+CONFIG_DVB_USB_EC168=m
+# CONFIG_DVB_USB_GL861 is not set
+CONFIG_DVB_USB_LME2510=m
+# CONFIG_DVB_USB_MXL111SF is not set
+CONFIG_DVB_USB_RTL28XXU=m
+CONFIG_DVB_USB_DVBSKY=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 is not set
+# CONFIG_VIDEO_EM28XX_ALSA is not set
+CONFIG_VIDEO_EM28XX_DVB=m
+CONFIG_VIDEO_EM28XX_RC=m
+# CONFIG_V4L_PLATFORM_DRIVERS is not set
+# CONFIG_V4L_MEM2MEM_DRIVERS is not set
+# CONFIG_V4L_TEST_DRIVERS is not set
+
+#
+# Supported MMC/SDIO adapters
+#
+CONFIG_SMS_SDIO_DRV=m
+# CONFIG_RADIO_ADAPTERS is not set
+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_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=y
+CONFIG_MEDIA_ATTACH=y
+CONFIG_VIDEO_IR_I2C=m
+
+#
+# Audio decoders, processors and mixers
+#
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_WM8775=m
+
+#
+# RDS decoders
+#
+
+#
+# Video decoders
+#
+CONFIG_VIDEO_SAA711X=m
+
+#
+# Video and audio decoders
+#
+CONFIG_VIDEO_CX25840=m
+
+#
+# Video encoders
+#
+
+#
+# Camera sensor devices
+#
+
+#
+# Flash devices
+#
+
+#
+# Video improvement chips
+#
+
+#
+# Audio/Video compression chips
+#
+
+#
+# Miscellaneous helper chips
+#
+
+#
+# Sensors used on soc_camera driver
+#
+CONFIG_MEDIA_TUNER=m
+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_MT20XX=m
+CONFIG_MEDIA_TUNER_MT2060=m
+CONFIG_MEDIA_TUNER_MT2063=m
+CONFIG_MEDIA_TUNER_MT2266=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_M88TS2022=m
+CONFIG_MEDIA_TUNER_TUA9001=m
+CONFIG_MEDIA_TUNER_SI2157=m
+CONFIG_MEDIA_TUNER_IT913X=m
+CONFIG_MEDIA_TUNER_R820T=m
+
+#
+# Multistandard (satellite) frontends
+#
+CONFIG_DVB_CX24120=m
+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_CX24123=m
+CONFIG_DVB_MT312=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_TDA10086=m
+CONFIG_DVB_TUNER_ITD1000=m
+CONFIG_DVB_TUNER_CX24113=m
+CONFIG_DVB_TDA826X=m
+CONFIG_DVB_CX24116=m
+CONFIG_DVB_SI21XX=m
+CONFIG_DVB_TS2020=m
+CONFIG_DVB_DS3000=m
+CONFIG_DVB_TDA10071=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_CX22702=m
+CONFIG_DVB_DRXD=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_TDA10048=m
+CONFIG_DVB_AF9013=m
+CONFIG_DVB_EC100=m
+CONFIG_DVB_CXD2820R=m
+CONFIG_DVB_RTL2830=m
+CONFIG_DVB_RTL2832=m
+CONFIG_DVB_SI2168=m
+CONFIG_DVB_AS102_FE=m
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_TDA10023=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+CONFIG_DVB_LGDT3305=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
+
+#
+# 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_LNBP21=m
+CONFIG_DVB_LNBP22=m
+CONFIG_DVB_ISL6421=m
+CONFIG_DVB_ISL6423=m
+CONFIG_DVB_A8293=m
+CONFIG_DVB_LGS8GXX=m
+CONFIG_DVB_ATBM8830=m
+CONFIG_DVB_IX2505V=m
+CONFIG_DVB_M88RS2000=m
+CONFIG_DVB_AF9033=m
+
+#
+# Tools to develop new frontends
+#
+# CONFIG_DVB_DUMMY_FE is not set
+
+#
+# Graphics support
+#
+
+#
+# Direct Rendering Manager
+#
+# CONFIG_DRM is not set
+
+#
+# Frame buffer Devices
+#
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+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 is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+CONFIG_FB_BCM2708=y
+# CONFIG_FB_ARMCLCD is not set
+# CONFIG_FB_OPENCORES is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_SMSCUFX is not set
+# CONFIG_FB_UDL is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_FB_AUO_K190X is not set
+# CONFIG_FB_SIMPLE is not set
+# CONFIG_FB_SSD1307 is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_LOGO is not set
+CONFIG_SOUND=y
+# CONFIG_SOUND_OSS_CORE is not set
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_DMAENGINE_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_COMPRESS_OFFLOAD=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_HRTIMER=m
+CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_MAX_CARDS=32
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# 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_AC97_CODEC=m
+# CONFIG_SND_DRIVERS is not set
+
+#
+# HD-Audio
+#
+CONFIG_SND_ARM=y
+# CONFIG_SND_ARMAACI is not set
+CONFIG_SND_BCM2835=m
+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_SOC=m
+CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM=y
+# CONFIG_SND_ATMEL_SOC is not set
+CONFIG_SND_BCM2708_SOC_I2S=m
+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m
+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m
+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m
+CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m
+CONFIG_SND_BCM2708_SOC_RPI_DAC=m
+CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m
+# 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 is not set
+# CONFIG_SND_SOC_FSL_SSI is not set
+# CONFIG_SND_SOC_FSL_SPDIF is not set
+# CONFIG_SND_SOC_FSL_ESAI is not set
+# CONFIG_SND_SOC_IMX_AUDMUX is not set
+CONFIG_SND_SOC_I2C_AND_SPI=m
+
+#
+# CODEC drivers
+#
+# CONFIG_SND_SOC_ADAU1701 is not set
+# CONFIG_SND_SOC_AK4104 is not set
+# CONFIG_SND_SOC_AK4554 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_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 is not set
+# CONFIG_SND_SOC_CS42XX8_I2C is not set
+# CONFIG_SND_SOC_HDMI_CODEC is not set
+# CONFIG_SND_SOC_ES8328 is not set
+# CONFIG_SND_SOC_PCM1681 is not set
+# CONFIG_SND_SOC_PCM1792A is not set
+CONFIG_SND_SOC_PCM512x=m
+CONFIG_SND_SOC_PCM512x_I2C=m
+# CONFIG_SND_SOC_PCM512x_SPI is not set
+CONFIG_SND_SOC_PCM1794A=m
+CONFIG_SND_SOC_PCM5102A=m
+# CONFIG_SND_SOC_SGTL5000 is not set
+# CONFIG_SND_SOC_SIRF_AUDIO_CODEC is not set
+# CONFIG_SND_SOC_SPDIF is not set
+# 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_STA350 is not set
+# CONFIG_SND_SOC_TAS2552 is not set
+# CONFIG_SND_SOC_TAS5086 is not set
+CONFIG_SND_SOC_TAS5713=m
+# CONFIG_SND_SOC_TLV320AIC31XX is not set
+# CONFIG_SND_SOC_TLV320AIC3X 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=m
+# CONFIG_SND_SOC_WM8903 is not set
+# CONFIG_SND_SOC_WM8962 is not set
+# 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 is not set
+CONFIG_HIDRAW=y
+# CONFIG_UHID is not set
+CONFIG_HID_GENERIC=y
+
+#
+# Special HID drivers
+#
+CONFIG_HID_A4TECH=y
+# CONFIG_HID_ACRUX is not set
+CONFIG_HID_APPLE=y
+# CONFIG_HID_APPLEIR is not set
+CONFIG_HID_AUREAL=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+# CONFIG_HID_PRODIKEYS is not set
+# CONFIG_HID_CP2112 is not set
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_DRAGONRISE=m
+CONFIG_DRAGONRISE_FF=y
+# CONFIG_HID_EMS_FF is not set
+# CONFIG_HID_ELECOM is not set
+# CONFIG_HID_ELO is not set
+CONFIG_HID_EZKEY=y
+# CONFIG_HID_HOLTEK is not set
+# CONFIG_HID_GT683R is not set
+# CONFIG_HID_HUION is not set
+# CONFIG_HID_KEYTOUCH is not set
+CONFIG_HID_KYE=y
+# CONFIG_HID_UCLOGIC is not set
+# CONFIG_HID_WALTOP is not set
+CONFIG_HID_GYRATION=y
+# CONFIG_HID_ICADE is not set
+CONFIG_HID_TWINHAN=y
+CONFIG_HID_KENSINGTON=y
+CONFIG_HID_LCPOWER=y
+CONFIG_HID_LENOVO=y
+CONFIG_HID_LOGITECH=y
+CONFIG_HID_LOGITECH_DJ=y
+CONFIG_LOGITECH_FF=y
+CONFIG_LOGIRUMBLEPAD2_FF=y
+CONFIG_LOGIG940_FF=y
+CONFIG_LOGIWHEELS_FF=y
+# CONFIG_HID_MAGICMOUSE is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+# CONFIG_HID_MULTITOUCH is not set
+# CONFIG_HID_NTRIG is not set
+CONFIG_HID_ORTEK=y
+CONFIG_HID_PANTHERLORD=y
+CONFIG_PANTHERLORD_FF=y
+CONFIG_HID_PENMOUNT=y
+CONFIG_HID_PETALYNX=y
+# CONFIG_HID_PICOLCD is not set
+# CONFIG_HID_PRIMAX is not set
+# CONFIG_HID_ROCCAT is not set
+# CONFIG_HID_SAITEK is not set
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_SONY_FF=y
+# CONFIG_HID_SPEEDLINK is not set
+# CONFIG_HID_STEELSERIES is not set
+CONFIG_HID_SPINELPLUS=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_HID_RMI=y
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+CONFIG_HID_TIVO=y
+CONFIG_HID_TOPSEED=y
+# CONFIG_HID_THINGM is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_WACOM is not set
+CONFIG_HID_WIIMOTE=m
+CONFIG_HID_XINMO=y
+# CONFIG_HID_ZEROPLUS is not set
+CONFIG_HID_ZYDACRON=y
+# CONFIG_HID_SENSOR_HUB is not set
+
+#
+# USB HID support
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+CONFIG_USB_HIDDEV=y
+
+#
+# I2C HID support
+#
+# CONFIG_I2C_HID is not set
+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=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEFAULT_PERSIST=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_OTG_FSM is not set
+CONFIG_USB_MON=m
+# 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 is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_FUSBH200_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_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+CONFIG_USB_DWCOTG=y
+# 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 is not set
+# CONFIG_USB_WDM is not set
+# 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 is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_STORAGE_ENE_UB6250 is not set
+CONFIG_USB_UAS=y
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USBIP_CORE is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_DWC3 is not set
+# CONFIG_USB_DWC2 is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_SIMPLE is not set
+# CONFIG_USB_SERIAL_AIRCABLE is not set
+# CONFIG_USB_SERIAL_ARK3116 is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+CONFIG_USB_SERIAL_CH341=m
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+CONFIG_USB_SERIAL_CP210X=m
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+CONFIG_USB_SERIAL_FTDI_SIO=m
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_F81232 is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+CONFIG_USB_SERIAL_IUU=m
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_METRO is not set
+# CONFIG_USB_SERIAL_MOS7720 is not set
+# CONFIG_USB_SERIAL_MOS7840 is not set
+# CONFIG_USB_SERIAL_MXUPORT is not set
+# CONFIG_USB_SERIAL_NAVMAN is not set
+CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_OTI6858 is not set
+# CONFIG_USB_SERIAL_QCAUX is not set
+# CONFIG_USB_SERIAL_QUALCOMM is not set
+# CONFIG_USB_SERIAL_SPCP8X5 is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
+# CONFIG_USB_SERIAL_SYMBOL is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OPTION is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_SERIAL_OPTICON is not set
+# CONFIG_USB_SERIAL_XSENS_MT is not set
+# CONFIG_USB_SERIAL_WISHBONE is not set
+# CONFIG_USB_SERIAL_SSU100 is not set
+# CONFIG_USB_SERIAL_QT2 is not set
+# CONFIG_USB_SERIAL_DEBUG is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_EHSET_TEST_FIXTURE is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+# CONFIG_USB_EZUSB_FX2 is not set
+# CONFIG_USB_HSIC_USB3503 is not set
+# CONFIG_USB_LINK_LAYER_TEST is not set
+
+#
+# USB Physical Layer drivers
+#
+# CONFIG_USB_PHY is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_AM335X_PHY_USB is not set
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ISP1301 is not set
+# CONFIG_USB_ULPI is not set
+# CONFIG_USB_GADGET is not set
+# CONFIG_USB_LED_TRIG is not set
+# CONFIG_UWB is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_CLKGATE is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_ARMMMCI is not set
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+# CONFIG_MMC_SDHCI_OF_ARASAN is not set
+# CONFIG_MMC_SDHCI_PXAV3 is not set
+# CONFIG_MMC_SDHCI_PXAV2 is not set
+CONFIG_MMC_BCM2835=y
+CONFIG_MMC_BCM2835_DMA=y
+CONFIG_MMC_BCM2835_PIO_DMA_BARRIER=2
+# CONFIG_MMC_SPI is not set
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_VUB300 is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MMC_USDHI6ROL0 is not set
+CONFIG_MMC_REALTEK_USB=m
+# CONFIG_MEMSTICK is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_LM3530 is not set
+# CONFIG_LEDS_LM3642 is not set
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=y
+# 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_PCA955X is not set
+# CONFIG_LEDS_PCA963X is not set
+# CONFIG_LEDS_DAC124S085 is not set
+# CONFIG_LEDS_BD2802 is not set
+# CONFIG_LEDS_LT3593 is not set
+# CONFIG_LEDS_TCA6507 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
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+# CONFIG_LEDS_TRIGGER_ONESHOT is not set
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+# CONFIG_LEDS_TRIGGER_CPU is not set
+# CONFIG_LEDS_TRIGGER_GPIO is not set
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+# CONFIG_LEDS_TRIGGER_TRANSIENT is not set
+# CONFIG_LEDS_TRIGGER_CAMERA is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_HCTOSYS is not set
+CONFIG_RTC_SYSTOHC=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# 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 is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+CONFIG_RTC_DRV_DS1307=m
+# 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 is not set
+# 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
+
+#
+# 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 is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_DS2404 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
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_PL030 is not set
+# CONFIG_RTC_DRV_PL031 is not set
+# CONFIG_RTC_DRV_SNVS is not set
+# CONFIG_RTC_DRV_XGENE is not set
+
+#
+# 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_AMBA_PL08X is not set
+# CONFIG_DW_DMAC_CORE is not set
+# CONFIG_DW_DMAC is not set
+# CONFIG_PL330_DMA is not set
+CONFIG_DMA_BCM2708=y
+# CONFIG_FSL_EDMA is not set
+# CONFIG_NBPFAXI_DMA is not set
+CONFIG_DMA_ENGINE=y
+CONFIG_DMA_VIRTUAL_CHANNELS=y
+CONFIG_DMA_OF=y
+
+#
+# DMA Clients
+#
+# CONFIG_ASYNC_TX_DMA is not set
+# 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_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+CONFIG_STAGING=y
+# CONFIG_PRISM2_USB is not set
+# CONFIG_COMEDI is not set
+# CONFIG_RTLLIB is not set
+CONFIG_R8712U=m
+# CONFIG_R8188EU is not set
+# CONFIG_LINE6_USB is not set
+CONFIG_VT6656=m
+# CONFIG_BCM_WIMAX is not set
+# CONFIG_FT1000 is not set
+
+#
+# Speakup console speech
+#
+# CONFIG_SPEAKUP is not set
+# CONFIG_TOUCHSCREEN_CLEARPAD_TM1217 is not set
+# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set
+CONFIG_STAGING_MEDIA=y
+# CONFIG_VIDEO_TCM825X is not set
+CONFIG_LIRC_STAGING=y
+CONFIG_LIRC_IGORPLUGUSB=m
+# CONFIG_LIRC_IMON is not set
+CONFIG_LIRC_RPI=m
+# CONFIG_LIRC_SASEM is not set
+# CONFIG_LIRC_SERIAL is not set
+# CONFIG_LIRC_SIR is not set
+CONFIG_LIRC_XBOX=m
+# CONFIG_LIRC_ZILOG is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+# CONFIG_USB_WPAN_HCD is not set
+# CONFIG_WIMAX_GDM72XX is not set
+# CONFIG_LTE_GDM724X is not set
+# CONFIG_LUSTRE_FS is not set
+# CONFIG_DGAP is not set
+# CONFIG_GS_FPGABOOT is not set
+
+#
+# SOC (System On Chip) specific Drivers
+#
+# CONFIG_SOC_TI 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_SI570 is not set
+# CONFIG_COMMON_CLK_PXA is not set
+# CONFIG_COMMON_CLK_QCOM is not set
+
+#
+# Hardware Spinlock drivers
+#
+
+#
+# Clock Source drivers
+#
+CONFIG_CLKSRC_OF=y
+CONFIG_ARM_ARCH_TIMER=y
+CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y
+# 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_VERSATILE is not set
+# CONFIG_MAILBOX is not set
+# CONFIG_IOMMU_SUPPORT is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+
+#
+# SOC (System On Chip) specific Drivers
+#
+# CONFIG_PM_DEVFREQ is not set
+CONFIG_EXTCON=m
+
+#
+# Extcon Device Drivers
+#
+CONFIG_EXTCON_ARIZONA=m
+# CONFIG_EXTCON_GPIO is not set
+# CONFIG_EXTCON_RT8973A is not set
+# CONFIG_EXTCON_SM5502 is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+# CONFIG_PWM is not set
+CONFIG_IRQCHIP=y
+# CONFIG_IPACK_BUS is not set
+# CONFIG_RESET_CONTROLLER is not set
+# CONFIG_FMC is not set
+
+#
+# PHY Subsystem
+#
+# CONFIG_GENERIC_PHY is not set
+# CONFIG_BCM_KONA_USB2_PHY is not set
+# CONFIG_POWERCAP is not set
+# CONFIG_MCB is not set
+
+#
+# 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_EXT23=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
+# 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 is not set
+CONFIG_JFS_FS=m
+# CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_SECURITY is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_XFS_FS=m
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# 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_BTRFS_FS=m
+# CONFIG_BTRFS_FS_POSIX_ACL is not set
+# 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_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 is not set
+# CONFIG_QUOTACTL is not set
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=m
+# CONFIG_CUSE is not set
+# CONFIG_OVERLAY_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE 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 is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=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 is not set
+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=y
+CONFIG_HFSPLUS_FS=y
+# 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_LOGFS is not set
+# CONFIG_CRAMFS is not set
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_FILE_CACHE is not set
+CONFIG_SQUASHFS_FILE_DIRECT=y
+# CONFIG_SQUASHFS_DECOMP_SINGLE is not set
+# CONFIG_SQUASHFS_DECOMP_MULTI is not set
+CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y
+# CONFIG_SQUASHFS_XATTR is not set
+CONFIG_SQUASHFS_ZLIB=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_SQUASHFS_XZ=y
+# 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 is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_F2FS_FS=y
+CONFIG_F2FS_STAT_FS=y
+# CONFIG_F2FS_FS_XATTR is not set
+CONFIG_F2FS_CHECK_FS=y
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V2=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_NFS_SWAP=y
+CONFIG_NFS_V4_1=y
+CONFIG_NFS_V4_2=y
+CONFIG_PNFS_FILE_LAYOUT=y
+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_NFSD is not set
+CONFIG_GRACE_PERIOD=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_SUNRPC_BACKCHANNEL=y
+CONFIG_SUNRPC_SWAP=y
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+CONFIG_CIFS=y
+CONFIG_CIFS_STATS=y
+CONFIG_CIFS_STATS2=y
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_UPCALL is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG is not set
+# CONFIG_CIFS_DFS_UPCALL is not set
+# CONFIG_CIFS_SMB2 is not set
+# CONFIG_NCP_FS 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 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+CONFIG_NLS_UTF8=y
+
+#
+# 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 is not set
+
+#
+# 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_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+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_DEBUG_PAGEALLOC is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON 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_SHIRQ is not set
+
+#
+# Debug Lockups and Hangs
+#
+CONFIG_LOCKUP_DETECTOR=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+# CONFIG_DETECT_HUNG_TASK is not set
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_SCHED_STACK_END_CHECK is not set
+# CONFIG_TIMER_STATS is not set
+# 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 is not set
+# 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_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_CPU_STALL_VERBOSE=y
+# CONFIG_RCU_CPU_STALL_INFO is not set
+# CONFIG_RCU_TRACE 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_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_TRACING_SUPPORT=y
+# CONFIG_FTRACE 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_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX 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_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 is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_LL is not set
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+# CONFIG_DEBUG_UART_PL01X is not set
+# CONFIG_DEBUG_UART_8250 is not set
+# CONFIG_DEBUG_UART_BCM63XX is not set
+CONFIG_UNCOMPRESS_INCLUDE="mach/uncompress.h"
+# CONFIG_OC_ETM is not set
+# CONFIG_PID_IN_CONTEXTIDR is not set
+# CONFIG_DEBUG_SET_MODULE_RONX is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_PERSISTENT_KEYRINGS is not set
+# CONFIG_BIG_KEYS is not set
+# CONFIG_ENCRYPTED_KEYS is not set
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# 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=m
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_USER is not set
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_PCRYPT is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_MCRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+# CONFIG_CRYPTO_GCM is not set
+CONFIG_CRYPTO_SEQIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_CMAC=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_CRC32 is not set
+# CONFIG_CRYPTO_CRCT10DIF is not set
+# CONFIG_CRYPTO_GHASH is not set
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA1_ARM=m
+CONFIG_CRYPTO_SHA256=y
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_AES_ARM=m
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+CONFIG_CRYPTO_LZO=m
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_DRBG_MENU is not set
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_ASYMMETRIC_KEY_TYPE is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_RAID6_PQ=m
+CONFIG_BITREVERSE=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_ARCH_USE_CMPXCHG_LOCKREF=y
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+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 is not set
+CONFIG_LIBCRC32C=m
+# CONFIG_CRC8 is not set
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_XZ_DEC=y
+# 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 is not set
+# CONFIG_XZ_DEC_ARMTHUMB is not set
+# CONFIG_XZ_DEC_SPARC is not set
+# CONFIG_XZ_DEC_BCJ is not set
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_GENERIC_ALLOCATOR=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_NLATTR=y
+CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
+CONFIG_AVERAGE=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+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_ARCH_HAS_SG_CHAIN is not set
+# CONFIG_VIRTUALIZATION is not set
diff --git a/projects/RPi2/options b/projects/RPi2/options
new file mode 100644
index 0000000000..f3b038f12e
--- /dev/null
+++ b/projects/RPi2/options
@@ -0,0 +1,152 @@
+################################################################################
+# setup system defaults
+################################################################################
+
+ # The TARGET_CPU variable controls which processor should be targeted for
+ # generated code.
+ case $TARGET_ARCH in
+ arm)
+ # TARGET_CPU:
+ # arm2 arm250 arm3 arm6 arm60 arm600 arm610 arm620 arm7 arm7m arm7d
+ # arm7dm arm7di arm7dmi arm70 arm700 arm700i arm710 arm710c
+ # arm7100 arm720 arm7500 arm7500fe arm7tdmi arm7tdmi-s arm710t
+ # arm720t arm740t strongarm strongarm110 strongarm1100
+ # strongarm1110 arm8 arm810 arm9 arm9e arm920 arm920t arm922t
+ # arm946e-s arm966e-s arm968e-s arm926ej-s arm940t arm9tdmi
+ # arm10tdmi arm1020t arm1026ej-s arm10e arm1020e arm1022e
+ # arm1136j-s arm1136jf-s mpcore mpcorenovfp arm1156t2-s
+ # arm1176jz-s arm1176jzf-s cortex-a8 cortex-a9 cortex-r4
+ # cortex-r4f cortex-m3 cortex-m1 xscale iwmmxt iwmmxt2 ep9312.
+ TARGET_CPU="cortex-a7"
+
+ # TARGET_FLOAT:
+ # Specifies which floating-point ABI to use. Permissible values are:
+ # soft softfp hard
+ TARGET_FLOAT="hard"
+
+ # TARGET_FPU:
+ # This specifies what floating point hardware (or hardware emulation) is
+ # available on the target. Permissible names are:
+ # fpa fpe2 fpe3 maverick vfp vfpv3 vfpv3-fp16 vfpv3-d16 vfpv3-d16-fp16
+ # vfpv3xd vfpv3xd-fp16 neon neon-fp16 vfpv4 vfpv4-d16 fpv4-sp-d16
+ # neon-vfpv4.
+ TARGET_FPU="neon"
+ ;;
+ esac
+
+ # Bootloader to use (syslinux / u-boot / bcm2835-bootloader)
+ BOOTLOADER="bcm2835-bootloader"
+
+ # u-boot version to use (default)
+ UBOOT_VERSION="default"
+
+ # Configuration for u-boot
+ UBOOT_CONFIG=""
+
+ # Target Configfile for u-boot
+ UBOOT_CONFIGFILE=""
+
+ # Kernel target for u-boot (default 'uImage' if BOOTLOADER=u-boot) (uImage / zImage)
+ KERNEL_UBOOT_TARGET=""
+
+ # Kernel extra targets to build
+ KERNEL_UBOOT_EXTRA_TARGET=""
+
+ # Additional kernel make parameters (for example to specify the u-boot loadaddress)
+ KERNEL_MAKE_EXTRACMD="dtbs"
+
+ # Kernel to use. values can be:
+ # default: default mainline kernel
+ LINUX="default"
+
+
+################################################################################
+# setup build defaults
+################################################################################
+
+ # Build optimizations (size/normal)
+ OPTIMIZATIONS="size"
+
+ # Project CFLAGS
+ PROJECT_CFLAGS=""
+
+ # LTO (Link Time Optimization) support
+ LTO_SUPPORT="yes"
+
+ # GOLD (Google Linker) support
+ GOLD_SUPPORT="yes"
+
+ # SquashFS compression method (gzip / lzo / xz)
+ SQUASHFS_COMPRESSION="lzo"
+
+
+################################################################################
+# setup project defaults
+################################################################################
+
+ # build and install ALSA Audio support (yes / no)
+ ALSA_SUPPORT="yes"
+
+ # OpenGL(X) implementation to use (no / Mesa)
+ OPENGL="no"
+
+ # OpenGL-ES implementation to use (no / bcm2835-driver / gpu-viv-bin-mx6q)
+ OPENGLES="bcm2835-driver"
+
+ # include uvesafb support (yes / no)
+ UVESAFB_SUPPORT="no"
+
+ # Displayserver to use (x11 / no)
+ DISPLAYSERVER="no"
+
+ # Windowmanager to use (ratpoison / fluxbox / none)
+ WINDOWMANAGER="none"
+
+ # Xorg Graphic drivers to use (all / i915,i965,r200,r300,r600,nvidia,nouveau)
+ # Space separated list is supported,
+ # e.g. GRAPHIC_DRIVERS="i915 i965 r300 r600 radeonsi nvidia nouveau"
+ GRAPHIC_DRIVERS=""
+
+ # KODI Player implementation to use (default / bcm2835-driver / libfslvpuwrap)
+ KODIPLAYER_DRIVER="bcm2835-driver"
+
+ # Modules to install in initramfs for early boot
+ INITRAMFS_MODULES=""
+
+ # additional Firmware to use (dvb-firmware, misc-firmware, wlan-firmware)
+ # Space separated list is supported,
+ # e.g. FIRMWARE="dvb-firmware misc-firmware wlan-firmware"
+ FIRMWARE="misc-firmware wlan-firmware dvb-firmware"
+
+ # build and install ATV IR remote support (yes / no)
+ ATVCLIENT_SUPPORT="no"
+
+ # build and install IRServer IR/LCD support (yes / no)
+ IRSERVER_SUPPORT="no"
+
+ # build with swap support (yes / no)
+ SWAP_SUPPORT="yes"
+
+ # swap support enabled per default (yes / no)
+ SWAP_ENABLED_DEFAULT="no"
+
+ # swapfile size if SWAP_SUPPORT=yes in MB
+ SWAPFILESIZE="128"
+
+ # build with installer (yes / no)
+ INSTALLER_SUPPORT="no"
+
+ # build and install 'RSXS' Screensaver (yes / no)
+ KODI_SCR_RSXS="no"
+
+ # build and install 'ProjectM' Visualization (yes / no)
+ KODI_VIS_PROJECTM="no"
+
+ # build and install 'GOOM' Visualization (yes / no)
+ KODI_VIS_GOOM="no"
+
+ # build and install 'FishBMC' Visualization (yes / no)
+ KODI_VIS_FISHBMC="no"
+
+ # kernel image name
+ KERNEL_NAME="kernel.img"
diff --git a/projects/RPi2/patches/kodi/kodi-001-helix_rpb_backports.patch b/projects/RPi2/patches/kodi/kodi-001-helix_rpb_backports.patch
new file mode 100644
index 0000000000..e44856aca5
--- /dev/null
+++ b/projects/RPi2/patches/kodi/kodi-001-helix_rpb_backports.patch
@@ -0,0 +1,6244 @@
+From dde30eb9bfceb3e1160778da78f9454f4a420c60 Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Mon, 7 Apr 2014 18:19:32 +0100
+Subject: [PATCH 01/61] [rbp/omxplayer] When opening a stream don't try to
+ update gui so often
+
+---
+ xbmc/dialogs/GUIDialogBusy.cpp | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/xbmc/dialogs/GUIDialogBusy.cpp b/xbmc/dialogs/GUIDialogBusy.cpp
+index e7cfcdd..20b99ad 100644
+--- a/xbmc/dialogs/GUIDialogBusy.cpp
++++ b/xbmc/dialogs/GUIDialogBusy.cpp
+@@ -68,7 +68,11 @@ bool CGUIDialogBusy::WaitOnEvent(CEvent &event, unsigned int displaytime /* = 10
+ if (dialog)
+ {
+ dialog->Show();
++#ifdef TARGET_RASPBERRY_PI
++ while(!event.WaitMSec(100))
++#else
+ while(!event.WaitMSec(1))
++#endif
+ {
+ g_windowManager.ProcessRenderLoop(false);
+ if (allowCancel && dialog->IsCanceled())
+
+From ec789b4201894bb0853901c8dfdb47cbf4050f4d Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Tue, 29 Apr 2014 15:23:22 +0100
+Subject: [PATCH 02/61] [ffmpeg] Speed up wtv index creation
+
+The index creation is O(N^2) with number of entries (typically thousands).
+On a Pi this can take more than 60 seconds to execute for a recording of a few hours.
+
+By replacing with an O(N) loop, this takes virtually zero time
+---
+ tools/depends/target/ffmpeg/Makefile | 3 +-
+ .../ffmpeg_Speed_up_wtv_index_creation.patch | 47 ++++++++++++++++++++++
+ 2 files changed, 49 insertions(+), 1 deletion(-)
+ create mode 100644 tools/depends/target/ffmpeg/ffmpeg_Speed_up_wtv_index_creation.patch
+
+diff --git a/tools/depends/target/ffmpeg/Makefile b/tools/depends/target/ffmpeg/Makefile
+index 0e08dcf..7ce982c 100644
+--- a/tools/depends/target/ffmpeg/Makefile
++++ b/tools/depends/target/ffmpeg/Makefile
+@@ -1,6 +1,6 @@
+ include ../../Makefile.include
+ include FFMPEG-VERSION
+-DEPS= ../../Makefile.include FFMPEG-VERSION Makefile
++DEPS= ../../Makefile.include FFMPEG-VERSION Makefile ffmpeg_Speed_up_wtv_index_creation.patch
+
+ # set to "yes" to enable patching
+ # we don't apply patches until we move to a vanilla ffmpeg tarball
+@@ -63,6 +63,7 @@ $(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 -p3 < ../ffmpeg_Speed_up_wtv_index_creation.patch
+ cd $(PLATFORM);\
+ CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" CPPFLAGS="$(CPPFLAGS)" LDFLAGS="$(LDFLAGS)" \
+ ./configure $(ffmpg_config)
+diff --git a/tools/depends/target/ffmpeg/ffmpeg_Speed_up_wtv_index_creation.patch b/tools/depends/target/ffmpeg/ffmpeg_Speed_up_wtv_index_creation.patch
+new file mode 100644
+index 0000000..4ac5636
+--- /dev/null
++++ b/tools/depends/target/ffmpeg/ffmpeg_Speed_up_wtv_index_creation.patch
+@@ -0,0 +1,47 @@
++commit 0e7427498cb1131671f6fe9d054245ae7e5a36f5
++Author: popcornmix
++Date: Tue Mar 25 19:43:07 2014 +0000
++
++ [ffmpeg] Speed up wtv index creation
++
++ The index creation is O(N^2) with number of entries (typically thousands).
++ On a Pi this can take more than 60 seconds to execute for a recording of a few hours.
++
++ By replacing with an O(N) loop, this takes virtually zero time
++
++diff --git a/lib/ffmpeg/libavformat/wtvdec.c b/lib/ffmpeg/libavformat/wtvdec.c
++index e423370..70898bd 100644
++--- a/lib/ffmpeg/libavformat/wtvdec.c
+++++ b/lib/ffmpeg/libavformat/wtvdec.c
++@@ -980,21 +980,23 @@ static int read_header(AVFormatContext *s)
++ pb = wtvfile_open(s, root, root_size, ff_timeline_table_0_entries_Events_le16);
++ if (pb) {
++ int i;
+++ AVIndexEntry *e = wtv->index_entries;
+++ AVIndexEntry *e_end = wtv->index_entries + wtv->nb_index_entries - 1;
+++ uint64_t last_position = 0;
++ while (1) {
++ uint64_t frame_nb = avio_rl64(pb);
++ uint64_t position = avio_rl64(pb);
+++ while (frame_nb > e->size && e <= e_end) {
+++ e->pos = last_position;
+++ e++;
+++ }
++ if (avio_feof(pb))
++ break;
++- for (i = wtv->nb_index_entries - 1; i >= 0; i--) {
++- AVIndexEntry *e = wtv->index_entries + i;
++- if (frame_nb > e->size)
++- break;
++- if (position > e->pos)
++- e->pos = position;
++- }
+++ last_position = position;
++ }
+++ e_end->pos = last_position;
++ wtvfile_close(pb);
++- st->duration = wtv->index_entries[wtv->nb_index_entries - 1].timestamp;
+++ st->duration = e_end->timestamp;
++ }
++ }
++ }
+
+From a386d39840eab40ee600b0e4a013d8460c73aac0 Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Sat, 2 Aug 2014 17:48:04 +0100
+Subject: [PATCH 03/61] [omx] Report decoded image name
+
+---
+ xbmc/cores/omxplayer/OMXImage.cpp | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/xbmc/cores/omxplayer/OMXImage.cpp b/xbmc/cores/omxplayer/OMXImage.cpp
+index aa413b9..22ec3f0 100644
+--- a/xbmc/cores/omxplayer/OMXImage.cpp
++++ b/xbmc/cores/omxplayer/OMXImage.cpp
+@@ -326,6 +326,7 @@ bool COMXImage::DecodeJpegToTexture(COMXImageFile *file, unsigned int width, uns
+ {
+ ret = true;
+ *userdata = tex;
++ CLog::Log(LOGDEBUG, "%s: decoded %s %dx%d", __func__, file->GetFilename(), width, height);
+ }
+ else
+ {
+
+From 66aca8521dba22df0f955c60e44f31e15e52c503 Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Sat, 8 Mar 2014 15:36:06 +0000
+Subject: [PATCH 04/61] [hifiberry] Hack: force it to be recognised as IEC958
+ capable to enable passthrough options
+
+---
+ xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp
+index df50940..2d853d6 100644
+--- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp
++++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp
+@@ -1333,6 +1333,10 @@ void CAESinkALSA::EnumerateDevice(AEDeviceInfoList &list, const std::string &dev
+ if (snd_card_get_name(cardNr, &cardName) == 0)
+ info.m_displayName = cardName;
+
++ // hack: hifiberry digi doesn't correctly report as iec958 device. Needs fixing in kernel driver
++ if (info.m_displayName == "snd_rpi_hifiberry_digi")
++ info.m_deviceType = AE_DEVTYPE_IEC958;
++
+ if (info.m_deviceType == AE_DEVTYPE_HDMI && info.m_displayName.size() > 5 &&
+ info.m_displayName.substr(info.m_displayName.size()-5) == " HDMI")
+ {
+
+From 8f1504b250c22778df7115c08e44fa4602c8b21e Mon Sep 17 00:00:00 2001
+From: Ben Avison
+Date: Wed, 11 Dec 2013 17:21:54 +0000
+Subject: [PATCH 05/61] Move the reference-counting of Begin and End calls from
+ DX and GL source files into GUIFontTTF.cpp.
+
+---
+ xbmc/guilib/GUIFontTTF.cpp | 21 ++++++
+ xbmc/guilib/GUIFontTTF.h | 6 +-
+ xbmc/guilib/GUIFontTTFDX.cpp | 79 ++++++++++------------
+ xbmc/guilib/GUIFontTTFDX.h | 4 +-
+ xbmc/guilib/GUIFontTTFGL.cpp | 154 ++++++++++++++++++++-----------------------
+ xbmc/guilib/GUIFontTTFGL.h | 4 +-
+ 6 files changed, 135 insertions(+), 133 deletions(-)
+
+diff --git a/xbmc/guilib/GUIFontTTF.cpp b/xbmc/guilib/GUIFontTTF.cpp
+index 4e6fb67..b1d7452 100644
+--- a/xbmc/guilib/GUIFontTTF.cpp
++++ b/xbmc/guilib/GUIFontTTF.cpp
+@@ -333,6 +333,27 @@ bool CGUIFontTTFBase::Load(const CStdString& strFilename, float height, float as
+ return true;
+ }
+
++void CGUIFontTTFBase::Begin()
++{
++ if (m_nestedBeginCount == 0 && m_texture != NULL && FirstBegin())
++ {
++ m_vertex_count = 0;
++ }
++ // Keep track of the nested begin/end calls.
++ m_nestedBeginCount++;
++}
++
++void CGUIFontTTFBase::End()
++{
++ if (m_nestedBeginCount == 0)
++ return;
++
++ if (--m_nestedBeginCount > 0)
++ return;
++
++ LastEnd();
++}
++
+ void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors, const vecText &text, uint32_t alignment, float maxPixelWidth, bool scrolling)
+ {
+ Begin();
+diff --git a/xbmc/guilib/GUIFontTTF.h b/xbmc/guilib/GUIFontTTF.h
+index 1714ed7..cd35d0f 100644
+--- a/xbmc/guilib/GUIFontTTF.h
++++ b/xbmc/guilib/GUIFontTTF.h
+@@ -79,8 +79,8 @@ class CGUIFontTTFBase
+
+ bool Load(const CStdString& strFilename, float height = 20.0f, float aspect = 1.0f, float lineSpacing = 1.0f, bool border = false);
+
+- virtual void Begin() = 0;
+- virtual void End() = 0;
++ void Begin();
++ void End();
+
+ const CStdString& GetFileName() const { return m_strFileName; };
+
+@@ -171,6 +171,8 @@ class CGUIFontTTFBase
+ XUTILS::auto_buffer m_fontFileInMemory; // used only in some cases, see CFreeTypeLibrary::GetFont()
+
+ private:
++ virtual bool FirstBegin() = 0;
++ virtual void LastEnd() = 0;
+ CGUIFontTTFBase(const CGUIFontTTFBase&);
+ CGUIFontTTFBase& operator=(const CGUIFontTTFBase&);
+ int m_referenceCount;
+diff --git a/xbmc/guilib/GUIFontTTFDX.cpp b/xbmc/guilib/GUIFontTTFDX.cpp
+index e3eba24..2f90668 100644
+--- a/xbmc/guilib/GUIFontTTFDX.cpp
++++ b/xbmc/guilib/GUIFontTTFDX.cpp
+@@ -51,65 +51,56 @@ CGUIFontTTFDX::~CGUIFontTTFDX(void)
+ free(m_index);
+ }
+
+-void CGUIFontTTFDX::Begin()
++bool CGUIFontTTFDX::FirstBegin()
+ {
+ LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice();
+
+ if (pD3DDevice == NULL)
++ {
+ CLog::Log(LOGERROR, __FUNCTION__" - failed to get Direct3D device");
++ return false;
++ }
+
+- if (m_nestedBeginCount == 0 && pD3DDevice != NULL && m_texture != NULL)
++ int unit = 0;
++ // just have to blit from our texture.
++ m_texture->BindToUnit(unit);
++ pD3DDevice->SetTextureStageState( unit, D3DTSS_COLOROP, D3DTOP_SELECTARG1 ); // only use diffuse
++ pD3DDevice->SetTextureStageState( unit, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
++ pD3DDevice->SetTextureStageState( unit, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
++ pD3DDevice->SetTextureStageState( unit, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
++ pD3DDevice->SetTextureStageState( unit, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
++ unit++;
++
++ if(g_Windowing.UseLimitedColor())
+ {
+- int unit = 0;
+- // just have to blit from our texture.
+- m_texture->BindToUnit(unit);
+- pD3DDevice->SetTextureStageState( unit, D3DTSS_COLOROP, D3DTOP_SELECTARG1 ); // only use diffuse
+- pD3DDevice->SetTextureStageState( unit, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
+- pD3DDevice->SetTextureStageState( unit, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
+- pD3DDevice->SetTextureStageState( unit, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
+- pD3DDevice->SetTextureStageState( unit, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
++ pD3DDevice->SetTextureStageState( unit, D3DTSS_COLOROP , D3DTOP_ADD );
++ pD3DDevice->SetTextureStageState( unit, D3DTSS_COLORARG1, D3DTA_CURRENT) ;
++ pD3DDevice->SetRenderState( D3DRS_TEXTUREFACTOR, D3DCOLOR_RGBA(16,16,16,0) );
++ pD3DDevice->SetTextureStageState( unit, D3DTSS_COLORARG2, D3DTA_TFACTOR );
+ unit++;
+-
+- if(g_Windowing.UseLimitedColor())
+- {
+- pD3DDevice->SetTextureStageState( unit, D3DTSS_COLOROP , D3DTOP_ADD );
+- pD3DDevice->SetTextureStageState( unit, D3DTSS_COLORARG1, D3DTA_CURRENT) ;
+- pD3DDevice->SetRenderState( D3DRS_TEXTUREFACTOR, D3DCOLOR_RGBA(16,16,16,0) );
+- pD3DDevice->SetTextureStageState( unit, D3DTSS_COLORARG2, D3DTA_TFACTOR );
+- unit++;
+- }
+-
+- // no other texture stages needed
+- pD3DDevice->SetTextureStageState( unit, D3DTSS_COLOROP, D3DTOP_DISABLE);
+- pD3DDevice->SetTextureStageState( unit, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+-
+- pD3DDevice->SetRenderState( D3DRS_ZENABLE, FALSE );
+- pD3DDevice->SetRenderState( D3DRS_FOGENABLE, FALSE );
+- pD3DDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
+- pD3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
+- pD3DDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
+- pD3DDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
+- pD3DDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
+- pD3DDevice->SetRenderState( D3DRS_LIGHTING, FALSE);
+-
+- pD3DDevice->SetFVF(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1);
+- m_vertex_count = 0;
+ }
+
+- // Keep track of the nested begin/end calls.
+- m_nestedBeginCount++;
++ // no other texture stages needed
++ pD3DDevice->SetTextureStageState( unit, D3DTSS_COLOROP, D3DTOP_DISABLE);
++ pD3DDevice->SetTextureStageState( unit, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
++
++ pD3DDevice->SetRenderState( D3DRS_ZENABLE, FALSE );
++ pD3DDevice->SetRenderState( D3DRS_FOGENABLE, FALSE );
++ pD3DDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
++ pD3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
++ pD3DDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
++ pD3DDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
++ pD3DDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
++ pD3DDevice->SetRenderState( D3DRS_LIGHTING, FALSE);
++
++ pD3DDevice->SetFVF(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1);
++ return true;
+ }
+
+-void CGUIFontTTFDX::End()
++void CGUIFontTTFDX::LastEnd()
+ {
+ LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice();
+
+- if (m_nestedBeginCount == 0)
+- return;
+-
+- if (--m_nestedBeginCount > 0)
+- return;
+-
+ if (m_vertex_count == 0)
+ return;
+
+diff --git a/xbmc/guilib/GUIFontTTFDX.h b/xbmc/guilib/GUIFontTTFDX.h
+index 0431085..17dfefe 100644
+--- a/xbmc/guilib/GUIFontTTFDX.h
++++ b/xbmc/guilib/GUIFontTTFDX.h
+@@ -41,8 +41,8 @@ class CGUIFontTTFDX : public CGUIFontTTFBase
+ CGUIFontTTFDX(const CStdString& strFileName);
+ virtual ~CGUIFontTTFDX(void);
+
+- virtual void Begin();
+- virtual void End();
++ virtual bool FirstBegin();
++ virtual void LastEnd();
+
+ protected:
+ virtual CBaseTexture* ReallocTexture(unsigned int& newHeight);
+diff --git a/xbmc/guilib/GUIFontTTFGL.cpp b/xbmc/guilib/GUIFontTTFGL.cpp
+index 6a8291b..97853fd 100644
+--- a/xbmc/guilib/GUIFontTTFGL.cpp
++++ b/xbmc/guilib/GUIFontTTFGL.cpp
+@@ -53,108 +53,96 @@ CGUIFontTTFGL::~CGUIFontTTFGL(void)
+ {
+ }
+
+-void CGUIFontTTFGL::Begin()
++bool CGUIFontTTFGL::FirstBegin()
+ {
+- if (m_nestedBeginCount == 0 && m_texture != NULL)
++ if (m_textureStatus == TEXTURE_REALLOCATED)
+ {
+- if (m_textureStatus == TEXTURE_REALLOCATED)
+- {
+- if (glIsTexture(m_nTexture))
+- g_TextureManager.ReleaseHwTexture(m_nTexture);
+- m_textureStatus = TEXTURE_VOID;
+- }
+-
+- if (m_textureStatus == TEXTURE_VOID)
+- {
+- // Have OpenGL generate a texture object handle for us
+- glGenTextures(1, (GLuint*) &m_nTexture);
++ if (glIsTexture(m_nTexture))
++ g_TextureManager.ReleaseHwTexture(m_nTexture);
++ m_textureStatus = TEXTURE_VOID;
++ }
+
+- // Bind the texture object
+- glBindTexture(GL_TEXTURE_2D, m_nTexture);
++ if (m_textureStatus == TEXTURE_VOID)
++ {
++ // Have OpenGL generate a texture object handle for us
++ glGenTextures(1, (GLuint*) &m_nTexture);
++
++ // Bind the texture object
++ glBindTexture(GL_TEXTURE_2D, m_nTexture);
+ #ifdef HAS_GL
+- glEnable(GL_TEXTURE_2D);
++ glEnable(GL_TEXTURE_2D);
+ #endif
+- // Set the texture's stretching properties
+- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
++ // Set the texture's stretching properties
++ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
++ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+- // Set the texture image -- THIS WORKS, so the pixels must be wrong.
+- glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, m_texture->GetWidth(), m_texture->GetHeight(), 0,
+- GL_ALPHA, GL_UNSIGNED_BYTE, 0);
+-
+- VerifyGLState();
+- m_textureStatus = TEXTURE_UPDATED;
+- }
++ // Set the texture image -- THIS WORKS, so the pixels must be wrong.
++ glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, m_texture->GetWidth(), m_texture->GetHeight(), 0,
++ GL_ALPHA, GL_UNSIGNED_BYTE, 0);
+
+- if (m_textureStatus == TEXTURE_UPDATED)
+- {
+- glBindTexture(GL_TEXTURE_2D, m_nTexture);
+- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, m_updateY1, m_texture->GetWidth(), m_updateY2 - m_updateY1, GL_ALPHA, GL_UNSIGNED_BYTE,
+- m_texture->GetPixels() + m_updateY1 * m_texture->GetPitch());
+- glDisable(GL_TEXTURE_2D);
+-
+- m_updateY1 = m_updateY2 = 0;
+- m_textureStatus = TEXTURE_READY;
+- }
++ VerifyGLState();
++ m_textureStatus = TEXTURE_UPDATED;
++ }
+
+- // Turn Blending On
+- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_ONE);
+- glEnable(GL_BLEND);
++ if (m_textureStatus == TEXTURE_UPDATED)
++ {
++ glBindTexture(GL_TEXTURE_2D, m_nTexture);
++ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, m_updateY1, m_texture->GetWidth(), m_updateY2 - m_updateY1, GL_ALPHA, GL_UNSIGNED_BYTE,
++ m_texture->GetPixels() + m_updateY1 * m_texture->GetPitch());
++ glDisable(GL_TEXTURE_2D);
++
++ m_updateY1 = m_updateY2 = 0;
++ m_textureStatus = TEXTURE_READY;
++ }
++
++ // Turn Blending On
++ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_ONE);
++ glEnable(GL_BLEND);
+ #ifdef HAS_GL
+- glEnable(GL_TEXTURE_2D);
++ glEnable(GL_TEXTURE_2D);
+ #endif
+- glBindTexture(GL_TEXTURE_2D, m_nTexture);
++ glBindTexture(GL_TEXTURE_2D, m_nTexture);
+
+ #ifdef HAS_GL
+- glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE);
+- glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_REPLACE);
+- glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR);
+- glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
+- glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
+- glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE0);
+- glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
+- glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PRIMARY_COLOR);
+- glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
+- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+- VerifyGLState();
++ glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE);
++ glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_REPLACE);
++ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR);
++ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
++ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
++ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE0);
++ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
++ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PRIMARY_COLOR);
++ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
++ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
++ VerifyGLState();
++
++ if(g_Windowing.UseLimitedColor())
++ {
++ glActiveTexture(GL_TEXTURE1);
++ glBindTexture(GL_TEXTURE_2D, m_nTexture); // dummy bind
++ glEnable(GL_TEXTURE_2D);
+
+- if(g_Windowing.UseLimitedColor())
+- {
+- glActiveTexture(GL_TEXTURE1);
+- glBindTexture(GL_TEXTURE_2D, m_nTexture); // dummy bind
+- glEnable(GL_TEXTURE_2D);
+-
+- const GLfloat rgba[4] = {16.0f / 255.0f, 16.0f / 255.0f, 16.0f / 255.0f, 0.0f};
+- glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE , GL_COMBINE);
+- glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, rgba);
+- glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB , GL_ADD);
+- glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_RGB , GL_PREVIOUS);
+- glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_RGB , GL_CONSTANT);
+- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB , GL_SRC_COLOR);
+- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB , GL_SRC_COLOR);
+- glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA , GL_REPLACE);
+- glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA , GL_PREVIOUS);
+- VerifyGLState();
+- }
++ const GLfloat rgba[4] = {16.0f / 255.0f, 16.0f / 255.0f, 16.0f / 255.0f, 0.0f};
++ glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE , GL_COMBINE);
++ glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, rgba);
++ glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB , GL_ADD);
++ glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_RGB , GL_PREVIOUS);
++ glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_RGB , GL_CONSTANT);
++ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB , GL_SRC_COLOR);
++ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB , GL_SRC_COLOR);
++ glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA , GL_REPLACE);
++ glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA , GL_PREVIOUS);
++ VerifyGLState();
++ }
+
+ #else
+- g_Windowing.EnableGUIShader(SM_FONTS);
++ g_Windowing.EnableGUIShader(SM_FONTS);
+ #endif
+-
+- m_vertex_count = 0;
+- }
+- // Keep track of the nested begin/end calls.
+- m_nestedBeginCount++;
++ return true;
+ }
+
+-void CGUIFontTTFGL::End()
++void CGUIFontTTFGL::LastEnd()
+ {
+- if (m_nestedBeginCount == 0)
+- return;
+-
+- if (--m_nestedBeginCount > 0)
+- return;
+-
+ #ifdef HAS_GL
+ glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
+
+diff --git a/xbmc/guilib/GUIFontTTFGL.h b/xbmc/guilib/GUIFontTTFGL.h
+index c0bb53a..735fb3a 100644
+--- a/xbmc/guilib/GUIFontTTFGL.h
++++ b/xbmc/guilib/GUIFontTTFGL.h
+@@ -41,8 +41,8 @@ class CGUIFontTTFGL : public CGUIFontTTFBase
+ CGUIFontTTFGL(const CStdString& strFileName);
+ virtual ~CGUIFontTTFGL(void);
+
+- virtual void Begin();
+- virtual void End();
++ virtual bool FirstBegin();
++ virtual void LastEnd();
+
+ protected:
+ virtual CBaseTexture* ReallocTexture(unsigned int& newHeight);
+
+From 441db2d2d13756a3c7c7a952ee3e48193bfcc06f Mon Sep 17 00:00:00 2001
+From: Ben Avison
+Date: Wed, 11 Dec 2013 18:47:54 +0000
+Subject: [PATCH 06/61] Convert CGUIFontTTFBase::m_vertex to be managed as a
+ std::vector.
+
+Also retired CGUIFontTTFBase::m_vertex_count and
+CGUIFontTTFBase::m_vertex_size because these can be derived from vector
+member functions.
+---
+ xbmc/guilib/GUIFontTTF.cpp | 29 +++++------------------------
+ xbmc/guilib/GUIFontTTF.h | 4 +---
+ xbmc/guilib/GUIFontTTFDX.cpp | 12 ++++++------
+ xbmc/guilib/GUIFontTTFGL.cpp | 12 ++++++------
+ 4 files changed, 18 insertions(+), 39 deletions(-)
+
+diff --git a/xbmc/guilib/GUIFontTTF.cpp b/xbmc/guilib/GUIFontTTF.cpp
+index b1d7452..686dddf 100644
+--- a/xbmc/guilib/GUIFontTTF.cpp
++++ b/xbmc/guilib/GUIFontTTF.cpp
+@@ -160,8 +160,7 @@ CGUIFontTTFBase::CGUIFontTTFBase(const CStdString& strFileName)
+ m_maxChars = 0;
+ m_nestedBeginCount = 0;
+
+- m_vertex_size = 4*1024;
+- m_vertex = (SVertex*)malloc(m_vertex_size * sizeof(SVertex));
++ m_vertex.reserve(4*1024);
+
+ m_face = NULL;
+ m_stroker = NULL;
+@@ -176,7 +175,6 @@ CGUIFontTTFBase::CGUIFontTTFBase(const CStdString& strFileName)
+ m_textureScaleX = m_textureScaleY = 0.0;
+ m_ellipsesWidth = m_height = 0.0f;
+ m_color = 0;
+- m_vertex_count = 0;
+ m_nTexture = 0;
+ }
+
+@@ -237,9 +235,7 @@ void CGUIFontTTFBase::Clear()
+ g_freeTypeLibrary.ReleaseStroker(m_stroker);
+ m_stroker = NULL;
+
+- free(m_vertex);
+- m_vertex = NULL;
+- m_vertex_count = 0;
++ m_vertex.clear();
+
+ m_strFileName.clear();
+ m_fontFileInMemory.clear();
+@@ -337,7 +333,7 @@ void CGUIFontTTFBase::Begin()
+ {
+ if (m_nestedBeginCount == 0 && m_texture != NULL && FirstBegin())
+ {
+- m_vertex_count = 0;
++ m_vertex.clear();
+ }
+ // Keep track of the nested begin/end calls.
+ m_nestedBeginCount++;
+@@ -770,22 +766,9 @@ void CGUIFontTTFBase::RenderCharacter(float posX, float posY, const Character *c
+ float tt = texture.y1 * m_textureScaleY;
+ float tb = texture.y2 * m_textureScaleY;
+
+- // grow the vertex buffer if required
+- if(m_vertex_count >= m_vertex_size)
+- {
+- m_vertex_size *= 2;
+- void* old = m_vertex;
+- m_vertex = (SVertex*)realloc(m_vertex, m_vertex_size * sizeof(SVertex));
+- if (!m_vertex)
+- {
+- free(old);
+- CLog::Log(LOGSEVERE, "%s: can't allocate %" PRIdS" bytes for texture", __FUNCTION__ , m_vertex_size * sizeof(SVertex));
+- return;
+- }
+- }
+-
++ m_vertex.resize(m_vertex.size() + 4);
++ SVertex* v = &m_vertex[m_vertex.size() - 4];
+ m_color = color;
+- SVertex* v = m_vertex + m_vertex_count;
+
+ unsigned char r = GET_R(color)
+ , g = GET_G(color)
+@@ -852,8 +835,6 @@ void CGUIFontTTFBase::RenderCharacter(float posX, float posY, const Character *c
+ v[3].y = y[2];
+ v[3].z = z[2];
+ #endif
+-
+- m_vertex_count+=4;
+ }
+
+ // Oblique code - original taken from freetype2 (ftsynth.c)
+diff --git a/xbmc/guilib/GUIFontTTF.h b/xbmc/guilib/GUIFontTTF.h
+index cd35d0f..5675725 100644
+--- a/xbmc/guilib/GUIFontTTF.h
++++ b/xbmc/guilib/GUIFontTTF.h
+@@ -158,9 +158,7 @@ class CGUIFontTTFBase
+
+ unsigned int m_nTexture;
+
+- SVertex* m_vertex;
+- int m_vertex_count;
+- int m_vertex_size;
++ std::vector m_vertex;
+
+ float m_textureScaleX;
+ float m_textureScaleY;
+diff --git a/xbmc/guilib/GUIFontTTFDX.cpp b/xbmc/guilib/GUIFontTTFDX.cpp
+index 2f90668..6ef8984 100644
+--- a/xbmc/guilib/GUIFontTTFDX.cpp
++++ b/xbmc/guilib/GUIFontTTFDX.cpp
+@@ -101,17 +101,17 @@ void CGUIFontTTFDX::LastEnd()
+ {
+ LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice();
+
+- if (m_vertex_count == 0)
++ if (m_vertex.size() == 0)
+ return;
+
+- unsigned index_size = m_vertex_size * 6 / 4;
++ unsigned index_size = m_vertex.capacity() * 6 / 4;
+ if(m_index_size < index_size)
+ {
+ uint16_t* id = (uint16_t*)calloc(index_size, sizeof(uint16_t));
+ if(id == NULL)
+ return;
+
+- for(int i = 0, b = 0; i < m_vertex_size; i += 4, b += 6)
++ for(int i = 0, b = 0; i < m_vertex.capacity(); i += 4, b += 6)
+ {
+ id[b+0] = i + 0;
+ id[b+1] = i + 1;
+@@ -140,11 +140,11 @@ void CGUIFontTTFDX::LastEnd()
+
+ pD3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST
+ , 0
+- , m_vertex_count
+- , m_vertex_count / 2
++ , m_vertex.size()
++ , m_vertex.size() / 2
+ , m_index
+ , D3DFMT_INDEX16
+- , m_vertex
++ , &m_vertex[0]
+ , sizeof(SVertex));
+ pD3DDevice->SetTransform(D3DTS_WORLD, &orig);
+
+diff --git a/xbmc/guilib/GUIFontTTFGL.cpp b/xbmc/guilib/GUIFontTTFGL.cpp
+index 97853fd..b76c6a5 100644
+--- a/xbmc/guilib/GUIFontTTFGL.cpp
++++ b/xbmc/guilib/GUIFontTTFGL.cpp
+@@ -146,13 +146,13 @@ void CGUIFontTTFGL::LastEnd()
+ #ifdef HAS_GL
+ glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
+
+- glColorPointer (4, GL_UNSIGNED_BYTE, sizeof(SVertex), (char*)m_vertex + offsetof(SVertex, r));
+- glVertexPointer (3, GL_FLOAT , sizeof(SVertex), (char*)m_vertex + offsetof(SVertex, x));
+- glTexCoordPointer(2, GL_FLOAT , sizeof(SVertex), (char*)m_vertex + offsetof(SVertex, u));
++ glColorPointer (4, GL_UNSIGNED_BYTE, sizeof(SVertex), (char*)&m_vertex[0] + offsetof(SVertex, r));
++ glVertexPointer (3, GL_FLOAT , sizeof(SVertex), (char*)&m_vertex[0] + offsetof(SVertex, x));
++ glTexCoordPointer(2, GL_FLOAT , sizeof(SVertex), (char*)&m_vertex[0] + offsetof(SVertex, u));
+ glEnableClientState(GL_COLOR_ARRAY);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+- glDrawArrays(GL_QUADS, 0, m_vertex_count);
++ glDrawArrays(GL_QUADS, 0, m_vertex.size());
+ glPopClientAttrib();
+
+ glActiveTexture(GL_TEXTURE1);
+@@ -168,10 +168,10 @@ void CGUIFontTTFGL::LastEnd()
+ GLint tex0Loc = g_Windowing.GUIShaderGetCoord0();
+
+ // stack object until VBOs will be used
+- std::vector vecVertices( 6 * (m_vertex_count / 4) );
++ std::vector vecVertices( 6 * (m_vertex.size() / 4) );
+ SVertex *vertices = &vecVertices[0];
+
+- for (int i=0; i
+Date: Mon, 16 Dec 2013 18:58:12 +0000
+Subject: [PATCH 07/61] CGUIFontTTFBase::RenderCharacter can now append to
+ arbitrary vectors of vertices rather than only CGUIFontTTFBase::m_vertex
+
+---
+ xbmc/guilib/GUIFontTTF.cpp | 12 +++++++-----
+ xbmc/guilib/GUIFontTTF.h | 2 +-
+ 2 files changed, 8 insertions(+), 6 deletions(-)
+
+diff --git a/xbmc/guilib/GUIFontTTF.cpp b/xbmc/guilib/GUIFontTTF.cpp
+index 686dddf..e6eb3f2 100644
+--- a/xbmc/guilib/GUIFontTTF.cpp
++++ b/xbmc/guilib/GUIFontTTF.cpp
+@@ -354,6 +354,8 @@ void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors
+ {
+ Begin();
+
++ std::vector &vertices = m_vertex;
++
+ // save the origin, which is scaled separately
+ m_originX = x;
+ m_originY = y;
+@@ -434,7 +436,7 @@ void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors
+
+ for (int i = 0; i < 3; i++)
+ {
+- RenderCharacter(startX + cursorX, startY, period, color, !scrolling);
++ RenderCharacter(startX + cursorX, startY, period, color, !scrolling, vertices);
+ cursorX += period->advance;
+ }
+ break;
+@@ -443,7 +445,7 @@ void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors
+ else if (maxPixelWidth > 0 && cursorX > maxPixelWidth)
+ break; // exceeded max allowed width - stop rendering
+
+- RenderCharacter(startX + cursorX, startY, ch, color, !scrolling);
++ RenderCharacter(startX + cursorX, startY, ch, color, !scrolling, vertices);
+ if ( alignment & XBFONT_JUSTIFIED )
+ {
+ if ((*pos & 0xffff) == L' ')
+@@ -700,7 +702,7 @@ bool CGUIFontTTFBase::CacheCharacter(wchar_t letter, uint32_t style, Character *
+ return true;
+ }
+
+-void CGUIFontTTFBase::RenderCharacter(float posX, float posY, const Character *ch, color_t color, bool roundX)
++void CGUIFontTTFBase::RenderCharacter(float posX, float posY, const Character *ch, color_t color, bool roundX, std::vector &vertices)
+ {
+ // actual image width isn't same as the character width as that is
+ // just baseline width and height should include the descent
+@@ -766,8 +768,8 @@ void CGUIFontTTFBase::RenderCharacter(float posX, float posY, const Character *c
+ float tt = texture.y1 * m_textureScaleY;
+ float tb = texture.y2 * m_textureScaleY;
+
+- m_vertex.resize(m_vertex.size() + 4);
+- SVertex* v = &m_vertex[m_vertex.size() - 4];
++ vertices.resize(vertices.size() + 4);
++ SVertex* v = &vertices[vertices.size() - 4];
+ m_color = color;
+
+ unsigned char r = GET_R(color)
+diff --git a/xbmc/guilib/GUIFontTTF.h b/xbmc/guilib/GUIFontTTF.h
+index 5675725..a5d44f4 100644
+--- a/xbmc/guilib/GUIFontTTF.h
++++ b/xbmc/guilib/GUIFontTTF.h
+@@ -111,7 +111,7 @@ class CGUIFontTTFBase
+ // Stuff for pre-rendering for speed
+ inline Character *GetCharacter(character_t letter);
+ bool CacheCharacter(wchar_t letter, uint32_t style, Character *ch);
+- void RenderCharacter(float posX, float posY, const Character *ch, color_t color, bool roundX);
++ void RenderCharacter(float posX, float posY, const Character *ch, color_t color, bool roundX, std::vector &vertices);
+ void ClearCharacterCache();
+
+ virtual CBaseTexture* ReallocTexture(unsigned int& newHeight) = 0;
+
+From 74a2b63b9dc70665bb3944c589b509b8a801aeb6 Mon Sep 17 00:00:00 2001
+From: Ben Avison
+Date: Wed, 15 Jan 2014 17:18:38 +0000
+Subject: [PATCH 08/61] Add a cache of font glyph bounding box vertices.
+
+This is implemented as a template because ultimately we will key on different
+parameters and store values of different types, depending upon whether we
+have a GLES or non-GLES backend, and for GLES, whether or not the currently
+applicable transformation matrices permit the use of hardware clipping.
+---
+ Kodi.xcodeproj/project.pbxproj | 10 ++
+ project/VS2010Express/XBMC.vcxproj | 4 +-
+ project/VS2010Express/XBMC.vcxproj.filters | 8 +-
+ xbmc/guilib/GUIFontCache.cpp | 105 ++++++++++++++
+ xbmc/guilib/GUIFontCache.h | 217 +++++++++++++++++++++++++++++
+ xbmc/guilib/GUIFontTTF.cpp | 181 +++++++++++++-----------
+ xbmc/guilib/GUIFontTTF.h | 5 +
+ xbmc/guilib/GUIFontTTFGL.cpp | 1 +
+ xbmc/guilib/GraphicContext.h | 1 +
+ xbmc/guilib/Makefile.in | 1 +
+ xbmc/guilib/TransformMatrix.h | 11 ++
+ 11 files changed, 458 insertions(+), 86 deletions(-)
+ create mode 100644 xbmc/guilib/GUIFontCache.cpp
+ create mode 100644 xbmc/guilib/GUIFontCache.h
+
+diff --git a/Kodi.xcodeproj/project.pbxproj b/Kodi.xcodeproj/project.pbxproj
+index 6dd3cf2..1f04a0b 100644
+--- a/Kodi.xcodeproj/project.pbxproj
++++ b/Kodi.xcodeproj/project.pbxproj
+@@ -168,6 +168,9 @@
+ 1D638128161E211E003603ED /* PeripheralImon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1D638126161E211E003603ED /* PeripheralImon.cpp */; };
+ 1DAFDB7C16DFDCA7007F8C68 /* PeripheralBusCEC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1DAFDB7A16DFDCA7007F8C68 /* PeripheralBusCEC.cpp */; };
+ 1DE0443515828F4B005DDB4D /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1DE0443315828F4B005DDB4D /* Exception.cpp */; };
++ 2F4564D51970129A00396109 /* GUIFontCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2F4564D31970129A00396109 /* GUIFontCache.cpp */; };
++ 2F4564D61970129A00396109 /* GUIFontCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2F4564D31970129A00396109 /* GUIFontCache.cpp */; };
++ 2F4564D71970129A00396109 /* GUIFontCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2F4564D31970129A00396109 /* GUIFontCache.cpp */; };
+ 32C631281423A90F00F18420 /* JpegIO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 32C631261423A90F00F18420 /* JpegIO.cpp */; };
+ 36A9443D15821E2800727135 /* DatabaseUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9443B15821E2800727135 /* DatabaseUtils.cpp */; };
+ 36A9444115821E7C00727135 /* SortUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9443F15821E7C00727135 /* SortUtils.cpp */; };
+@@ -4018,6 +4021,8 @@
+ 1DAFDB7B16DFDCA7007F8C68 /* PeripheralBusCEC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PeripheralBusCEC.h; sourceTree = ""; };
+ 1DE0443315828F4B005DDB4D /* Exception.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Exception.cpp; path = commons/Exception.cpp; sourceTree = ""; };
+ 1DE0443415828F4B005DDB4D /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Exception.h; path = commons/Exception.h; sourceTree = ""; };
++ 2F4564D31970129A00396109 /* GUIFontCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIFontCache.cpp; sourceTree = ""; };
++ 2F4564D41970129A00396109 /* GUIFontCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIFontCache.h; sourceTree = ""; };
+ 32C631261423A90F00F18420 /* JpegIO.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JpegIO.cpp; sourceTree = ""; };
+ 32C631271423A90F00F18420 /* JpegIO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JpegIO.h; sourceTree = ""; };
+ 36A9443B15821E2800727135 /* DatabaseUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DatabaseUtils.cpp; sourceTree = ""; };
+@@ -6532,6 +6537,8 @@
+ 18B7C7101294222D009E7A26 /* GUIFixedListContainer.h */,
+ 18B7C76B1294222E009E7A26 /* GUIFont.cpp */,
+ 18B7C7111294222D009E7A26 /* GUIFont.h */,
++ 2F4564D31970129A00396109 /* GUIFontCache.cpp */,
++ 2F4564D41970129A00396109 /* GUIFontCache.h */,
+ 18B7C76C1294222E009E7A26 /* GUIFontManager.cpp */,
+ 18B7C7121294222D009E7A26 /* GUIFontManager.h */,
+ 18B7C76D1294222E009E7A26 /* GUIFontTTF.cpp */,
+@@ -11038,6 +11045,7 @@
+ 7C5608C70F1754930056433A /* ExternalPlayer.cpp in Sources */,
+ F584E12E0F257C5100DB26A5 /* HTTPDirectory.cpp in Sources */,
+ F54C51D20F1E783200D46E3C /* GUIDialogKaraokeSongSelector.cpp in Sources */,
++ 2F4564D51970129A00396109 /* GUIFontCache.cpp in Sources */,
+ F54C51D50F1E784800D46E3C /* karaokelyricscdg.cpp in Sources */,
+ F54C51D80F1E785700D46E3C /* karaokelyrics.cpp in Sources */,
+ F54C51E50F1E787700D46E3C /* karaokelyricstextkar.cpp in Sources */,
+@@ -12712,6 +12720,7 @@
+ DFF0F45B17528350002DA3A4 /* Control.cpp in Sources */,
+ DFF0F45C17528350002DA3A4 /* Dialog.cpp in Sources */,
+ DFF0F45D17528350002DA3A4 /* File.cpp in Sources */,
++ 2F4564D71970129A00396109 /* GUIFontCache.cpp in Sources */,
+ DFF0F45E17528350002DA3A4 /* InfoTagMusic.cpp in Sources */,
+ DFF0F45F17528350002DA3A4 /* InfoTagVideo.cpp in Sources */,
+ DFF0F46017528350002DA3A4 /* Keyboard.cpp in Sources */,
+@@ -13507,6 +13516,7 @@
+ E499131D174E5DAD00741B6D /* GUIVisualisationControl.cpp in Sources */,
+ E499131E174E5DAD00741B6D /* GUIWindow.cpp in Sources */,
+ E499131F174E5DAD00741B6D /* GUIWindowManager.cpp in Sources */,
++ 2F4564D61970129A00396109 /* GUIFontCache.cpp in Sources */,
+ E4991320174E5DAD00741B6D /* GUIWrappingListContainer.cpp in Sources */,
+ E4991321174E5DAD00741B6D /* imagefactory.cpp in Sources */,
+ E4991322174E5DAD00741B6D /* IWindowManagerCallback.cpp in Sources */,
+diff --git a/project/VS2010Express/XBMC.vcxproj b/project/VS2010Express/XBMC.vcxproj
+index aca7b82..2d735052 100644
+--- a/project/VS2010Express/XBMC.vcxproj
++++ b/project/VS2010Express/XBMC.vcxproj
+@@ -426,6 +426,7 @@
+
+
+
++
+
+
+
+@@ -1751,6 +1752,7 @@
+
+
+
++
+
+
+
+@@ -2552,4 +2554,4 @@
+
+
+
+-
+\ No newline at end of file
++
+diff --git a/project/VS2010Express/XBMC.vcxproj.filters b/project/VS2010Express/XBMC.vcxproj.filters
+index 7603447..506b565 100644
+--- a/project/VS2010Express/XBMC.vcxproj.filters
++++ b/project/VS2010Express/XBMC.vcxproj.filters
+@@ -994,6 +994,9 @@
+
+ guilib
+
++
++ guilib
++
+
+ guilib
+
+@@ -3894,6 +3897,9 @@
+
+ guilib
+
++
++ guilib
++
+
+ guilib
+
+@@ -6073,4 +6079,4 @@
+ interfaces\swig
+
+
+-
+\ No newline at end of file
++
+diff --git a/xbmc/guilib/GUIFontCache.cpp b/xbmc/guilib/GUIFontCache.cpp
+new file mode 100644
+index 0000000..2c72f9c
+--- /dev/null
++++ b/xbmc/guilib/GUIFontCache.cpp
+@@ -0,0 +1,105 @@
++/*
++ * 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
++#include
++#include "utils/StdString.h" // required by GUIFontTTF.h
++#include "GUIFontTTF.h"
++#include "GraphicContext.h"
++
++template
++void CGUIFontCacheEntry::Reassign::operator()(CGUIFontCacheEntry &entry)
++{
++ entry.m_key.m_pos = m_key.m_pos;
++ entry.m_key.m_colors.assign(m_key.m_colors.begin(), m_key.m_colors.end());
++ entry.m_key.m_text.assign(m_key.m_text.begin(), m_key.m_text.end());
++ entry.m_key.m_alignment = m_key.m_alignment;
++ entry.m_key.m_maxPixelWidth = m_key.m_maxPixelWidth;
++ entry.m_key.m_scrolling = m_key.m_scrolling;
++ entry.m_matrix = m_key.m_matrix;
++ entry.m_key.m_scaleX = m_key.m_scaleX;
++ entry.m_key.m_scaleY = m_key.m_scaleY;
++
++ entry.m_lastUsedMillis = m_nowMillis;
++ entry.m_value.clear();
++}
++
++template
++CGUIFontCacheEntry::~CGUIFontCacheEntry()
++{
++ delete &m_key.m_colors;
++ delete &m_key.m_text;
++ m_value.clear();
++}
++
++template
++Value &CGUIFontCache::Lookup(Position &pos,
++ const vecColors &colors, const vecText &text,
++ uint32_t alignment, float maxPixelWidth,
++ bool scrolling,
++ unsigned int nowMillis, bool &dirtyCache)
++{
++ const CGUIFontCacheKey key(pos,
++ const_cast(colors), const_cast(text),
++ alignment, maxPixelWidth,
++ scrolling, g_graphicsContext.GetGUIMatrix(),
++ g_graphicsContext.GetGUIScaleX(), g_graphicsContext.GetGUIScaleY());
++ EntryHashIterator i = m_list.template get().find(key);
++ if (i == m_list.template get().end())
++ {
++ /* Cache miss */
++ EntryAgeIterator oldest = m_list.template get().begin();
++ if (!m_list.template get().empty() && nowMillis - oldest->m_lastUsedMillis > FONT_CACHE_TIME_LIMIT)
++ {
++ /* The oldest existing entry is old enough to expire and reuse */
++ m_list.template get().modify(m_list.template project(oldest), typename CGUIFontCacheEntry::Reassign(key, nowMillis));
++ m_list.template get().relocate(m_list.template get().end(), oldest);
++ }
++ else
++ {
++ /* We need a new entry instead */
++ /* Yes, this causes the creation an destruction of a temporary entry, but
++ * this code ought to only be used infrequently, when the cache needs to grow */
++ m_list.template get().push_back(CGUIFontCacheEntry(*this, key, nowMillis));
++ }
++ dirtyCache = true;
++ return (--m_list.template get().end())->m_value;
++ }
++ else
++ {
++ /* Cache hit */
++ /* Update time in entry and move to the back of the list */
++ i->m_lastUsedMillis = nowMillis;
++ m_list.template get().relocate(m_list.template get().end(), m_list.template project(i));
++ dirtyCache = false;
++ return i->m_value;
++ }
++}
++
++template
++void CGUIFontCache::Flush()
++{
++ m_list.template get().clear();
++}
++
++template void CGUIFontCacheEntry::Reassign::operator()(CGUIFontCacheEntry &entry);
++template CGUIFontCacheEntry::~CGUIFontCacheEntry();
++template CGUIFontCacheStaticValue &CGUIFontCache::Lookup(CGUIFontCacheStaticPosition &, const vecColors &, const vecText &, uint32_t, float, bool, unsigned int, bool &);
++template void CGUIFontCache::Flush();
+diff --git a/xbmc/guilib/GUIFontCache.h b/xbmc/guilib/GUIFontCache.h
+new file mode 100644
+index 0000000..ef65845
+--- /dev/null
++++ b/xbmc/guilib/GUIFontCache.h
+@@ -0,0 +1,217 @@
++/*!
++\file GUIFontCache.h
++\brief
++*/
++
++#ifndef CGUILIB_GUIFONTCACHE_H
++#define CGUILIB_GUIFONTCACHE_H
++#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
++#include
++#include
++
++#include
++#include
++
++#include "boost/multi_index_container.hpp"
++#include "boost/multi_index/sequenced_index.hpp"
++#include "boost/multi_index/hashed_index.hpp"
++#include "boost/multi_index/member.hpp"
++
++#include "TransformMatrix.h"
++
++using namespace boost::multi_index;
++
++#define FONT_CACHE_TIME_LIMIT (1000)
++
++template class CGUIFontCache;
++class CGUIFontTTFBase;
++
++template
++struct CGUIFontCacheKey
++{
++ Position m_pos;
++ vecColors &m_colors;
++ vecText &m_text;
++ uint32_t m_alignment;
++ float m_maxPixelWidth;
++ bool m_scrolling;
++ const TransformMatrix &m_matrix;
++ float m_scaleX;
++ float m_scaleY;
++
++ CGUIFontCacheKey(Position pos,
++ vecColors &colors, vecText &text,
++ uint32_t alignment, float maxPixelWidth,
++ bool scrolling, const TransformMatrix &matrix,
++ float scaleX, float scaleY) :
++ m_pos(pos),
++ m_colors(colors), m_text(text),
++ m_alignment(alignment), m_maxPixelWidth(maxPixelWidth),
++ m_scrolling(scrolling), m_matrix(matrix),
++ m_scaleX(scaleX), m_scaleY(scaleY)
++ {}
++};
++
++template
++struct CGUIFontCacheEntry
++{
++ const CGUIFontCache &m_cache;
++ CGUIFontCacheKey m_key;
++ TransformMatrix m_matrix;
++
++ /* These need to be declared as mutable to get round the fact that only
++ * const iterators are available. These fields do not affect comparison or
++ * hash functors, so from the container's point of view, they are mutable. */
++ mutable unsigned int m_lastUsedMillis;
++ mutable Value m_value;
++
++ CGUIFontCacheEntry(const CGUIFontCache &cache, const CGUIFontCacheKey &key, unsigned int nowMillis) :
++ m_cache(cache),
++ m_key(key.m_pos,
++ *new vecColors, *new vecText,
++ key.m_alignment, key.m_maxPixelWidth,
++ key.m_scrolling, m_matrix,
++ key.m_scaleX, key.m_scaleY),
++ m_lastUsedMillis(nowMillis)
++ {
++ m_key.m_colors.assign(key.m_colors.begin(), key.m_colors.end());
++ m_key.m_text.assign(key.m_text.begin(), key.m_text.end());
++ m_matrix = key.m_matrix;
++ }
++
++ CGUIFontCacheEntry(const CGUIFontCacheEntry &other) :
++ m_cache(other.m_cache),
++ m_key(other.m_key.m_pos,
++ *new vecColors, *new vecText,
++ other.m_key.m_alignment, other.m_key.m_maxPixelWidth,
++ other.m_key.m_scrolling, m_matrix,
++ other.m_key.m_scaleX, other.m_key.m_scaleY),
++ m_lastUsedMillis(other.m_lastUsedMillis),
++ m_value(other.m_value)
++ {
++ m_key.m_colors.assign(other.m_key.m_colors.begin(), other.m_key.m_colors.end());
++ m_key.m_text.assign(other.m_key.m_text.begin(), other.m_key.m_text.end());
++ m_matrix = other.m_key.m_matrix;
++ }
++
++ struct Reassign
++ {
++ Reassign(const CGUIFontCacheKey &key, unsigned int nowMillis) : m_key(key), m_nowMillis(nowMillis) {}
++ void operator()(CGUIFontCacheEntry &entry);
++ private:
++ const CGUIFontCacheKey &m_key;
++ unsigned int m_nowMillis;
++ };
++
++ ~CGUIFontCacheEntry();
++};
++
++template
++struct CGUIFontCacheHash
++{
++ size_t operator()(const CGUIFontCacheKey &key) const
++ {
++ /* Not much effort has gone into choosing this hash function */
++ size_t hash = 0, i;
++ for (i = 0; i < 3 && i < key.m_text.size(); ++i)
++ hash += key.m_text[i];
++ if (key.m_colors.size())
++ hash += key.m_colors[0];
++ hash += MatrixHashContribution(key);
++ return hash;
++ }
++};
++
++template
++struct CGUIFontCacheKeysMatch
++{
++ bool operator()(const CGUIFontCacheKey &a, const CGUIFontCacheKey &b) const
++ {
++ return a.m_text == b.m_text &&
++ a.m_colors == b.m_colors &&
++ a.m_alignment == b.m_alignment &&
++ a.m_scrolling == b.m_scrolling &&
++ a.m_maxPixelWidth == b.m_maxPixelWidth &&
++ Match(a.m_pos, a.m_matrix, b.m_pos, b.m_matrix, a.m_scrolling) &&
++ a.m_scaleX == b.m_scaleX &&
++ a.m_scaleY == b.m_scaleY;
++ }
++};
++
++template
++class CGUIFontCache
++{
++ /* Empty structs used as tags to identify indexes */
++ struct Age {};
++ struct Hash {};
++
++ typedef multi_index_container<
++ CGUIFontCacheEntry,
++ indexed_by<
++ sequenced >,
++ hashed_unique, member, CGUIFontCacheKey, &CGUIFontCacheEntry::m_key>, CGUIFontCacheHash, CGUIFontCacheKeysMatch >
++ >
++ > EntryList;
++
++ typedef typename EntryList::template index::type::iterator EntryAgeIterator;
++ typedef typename EntryList::template index::type::iterator EntryHashIterator;
++
++ EntryList m_list;
++
++public:
++ const CGUIFontTTFBase &m_font;
++
++ CGUIFontCache(CGUIFontTTFBase &font) : m_font(font) {}
++ Value &Lookup(Position &pos,
++ const vecColors &colors, const vecText &text,
++ uint32_t alignment, float maxPixelWidth,
++ bool scrolling,
++ unsigned int nowMillis, bool &dirtyCache);
++ void Flush();
++};
++
++struct CGUIFontCacheStaticPosition
++{
++ float m_x;
++ float m_y;
++ CGUIFontCacheStaticPosition(float x, float y) : m_x(x), m_y(y) {}
++};
++
++typedef std::vector CGUIFontCacheStaticValue;
++
++inline bool Match(const CGUIFontCacheStaticPosition &a, const TransformMatrix &a_m,
++ const CGUIFontCacheStaticPosition &b, const TransformMatrix &b_m,
++ bool scrolling)
++{
++ return a.m_x == b.m_x && a.m_y == b.m_y && a_m == b_m;
++}
++
++inline float MatrixHashContribution(const CGUIFontCacheKey &a)
++{
++ /* Ensure horizontally translated versions end up in different buckets */
++ return a.m_matrix.m[0][3];
++}
++
++#endif
+diff --git a/xbmc/guilib/GUIFontTTF.cpp b/xbmc/guilib/GUIFontTTF.cpp
+index e6eb3f2..6a40e9c 100644
+--- a/xbmc/guilib/GUIFontTTF.cpp
++++ b/xbmc/guilib/GUIFontTTF.cpp
+@@ -29,6 +29,7 @@
+ #include "windowing/WindowingFactory.h"
+ #include "URL.h"
+ #include "filesystem/File.h"
++#include "threads/SystemClock.h"
+
+ #include
+
+@@ -153,7 +154,7 @@ class CFreeTypeLibrary
+ XBMC_GLOBAL_REF(CFreeTypeLibrary, g_freeTypeLibrary); // our freetype library
+ #define g_freeTypeLibrary XBMC_GLOBAL_USE(CFreeTypeLibrary)
+
+-CGUIFontTTFBase::CGUIFontTTFBase(const CStdString& strFileName)
++CGUIFontTTFBase::CGUIFontTTFBase(const CStdString& strFileName) : m_staticCache(*this)
+ {
+ m_texture = NULL;
+ m_char = NULL;
+@@ -354,108 +355,120 @@ void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors
+ {
+ Begin();
+
+- std::vector &vertices = m_vertex;
+-
+- // save the origin, which is scaled separately
+- m_originX = x;
+- m_originY = y;
+-
+- // Check if we will really need to truncate or justify the text
+- if ( alignment & XBFONT_TRUNCATED )
++ bool dirtyCache;
++ CGUIFontCacheStaticPosition staticPos(x, y);
++ std::vector &vertices = m_staticCache.Lookup(staticPos,
++ colors, text,
++ alignment, maxPixelWidth,
++ scrolling,
++ XbmcThreads::SystemClockMillis(),
++ dirtyCache);
++ if (dirtyCache)
+ {
+- if ( maxPixelWidth <= 0.0f || GetTextWidthInternal(text.begin(), text.end()) <= maxPixelWidth)
+- alignment &= ~XBFONT_TRUNCATED;
+- }
+- else if ( alignment & XBFONT_JUSTIFIED )
+- {
+- if ( maxPixelWidth <= 0.0f )
+- alignment &= ~XBFONT_JUSTIFIED;
+- }
++ // save the origin, which is scaled separately
++ m_originX = x;
++ m_originY = y;
+
+- // calculate sizing information
+- float startX = 0;
+- float startY = (alignment & XBFONT_CENTER_Y) ? -0.5f*m_cellHeight : 0; // vertical centering
++ // Check if we will really need to truncate or justify the text
++ if ( alignment & XBFONT_TRUNCATED )
++ {
++ if ( maxPixelWidth <= 0.0f || GetTextWidthInternal(text.begin(), text.end()) <= maxPixelWidth)
++ alignment &= ~XBFONT_TRUNCATED;
++ }
++ else if ( alignment & XBFONT_JUSTIFIED )
++ {
++ if ( maxPixelWidth <= 0.0f )
++ alignment &= ~XBFONT_JUSTIFIED;
++ }
+
+- if ( alignment & (XBFONT_RIGHT | XBFONT_CENTER_X) )
+- {
+- // Get the extent of this line
+- float w = GetTextWidthInternal( text.begin(), text.end() );
++ // calculate sizing information
++ float startX = 0;
++ float startY = (alignment & XBFONT_CENTER_Y) ? -0.5f*m_cellHeight : 0; // vertical centering
+
+- if ( alignment & XBFONT_TRUNCATED && w > maxPixelWidth + 0.5f ) // + 0.5f due to rounding issues
+- w = maxPixelWidth;
++ if ( alignment & (XBFONT_RIGHT | XBFONT_CENTER_X) )
++ {
++ // Get the extent of this line
++ float w = GetTextWidthInternal( text.begin(), text.end() );
+
+- if ( alignment & XBFONT_CENTER_X)
+- w *= 0.5f;
+- // Offset this line's starting position
+- startX -= w;
+- }
++ if ( alignment & XBFONT_TRUNCATED && w > maxPixelWidth + 0.5f ) // + 0.5f due to rounding issues
++ w = maxPixelWidth;
+
+- float spacePerLetter = 0; // for justification effects
+- if ( alignment & XBFONT_JUSTIFIED )
+- {
+- // first compute the size of the text to render in both characters and pixels
+- unsigned int lineChars = 0;
+- float linePixels = 0;
+- for (vecText::const_iterator pos = text.begin(); pos != text.end(); ++pos)
++ if ( alignment & XBFONT_CENTER_X)
++ w *= 0.5f;
++ // Offset this line's starting position
++ startX -= w;
++ }
++
++ float spacePerLetter = 0; // for justification effects
++ if ( alignment & XBFONT_JUSTIFIED )
+ {
+- Character *ch = GetCharacter(*pos);
+- if (ch)
+- { // spaces have multiple times the justification spacing of normal letters
+- lineChars += ((*pos & 0xffff) == L' ') ? justification_word_weight : 1;
+- linePixels += ch->advance;
++ // first compute the size of the text to render in both characters and pixels
++ unsigned int lineChars = 0;
++ float linePixels = 0;
++ for (vecText::const_iterator pos = text.begin(); pos != text.end(); ++pos)
++ {
++ Character *ch = GetCharacter(*pos);
++ if (ch)
++ { // spaces have multiple times the justification spacing of normal letters
++ lineChars += ((*pos & 0xffff) == L' ') ? justification_word_weight : 1;
++ linePixels += ch->advance;
++ }
+ }
++ if (lineChars > 1)
++ spacePerLetter = (maxPixelWidth - linePixels) / (lineChars - 1);
+ }
+- if (lineChars > 1)
+- spacePerLetter = (maxPixelWidth - linePixels) / (lineChars - 1);
+- }
+- float cursorX = 0; // current position along the line
+-
+- for (vecText::const_iterator pos = text.begin(); pos != text.end(); ++pos)
+- {
+- // If starting text on a new line, determine justification effects
+- // Get the current letter in the CStdString
+- color_t color = (*pos & 0xff0000) >> 16;
+- if (color >= colors.size())
+- color = 0;
+- color = colors[color];
++ float cursorX = 0; // current position along the line
+
+- // grab the next character
+- Character *ch = GetCharacter(*pos);
+- if (!ch) continue;
+-
+- if ( alignment & XBFONT_TRUNCATED )
++ for (vecText::const_iterator pos = text.begin(); pos != text.end(); ++pos)
+ {
+- // Check if we will be exceeded the max allowed width
+- if ( cursorX + ch->advance + 3 * m_ellipsesWidth > maxPixelWidth )
+- {
+- // Yup. Let's draw the ellipses, then bail
+- // Perhaps we should really bail to the next line in this case??
+- Character *period = GetCharacter(L'.');
+- if (!period)
+- break;
++ // If starting text on a new line, determine justification effects
++ // Get the current letter in the CStdString
++ color_t color = (*pos & 0xff0000) >> 16;
++ if (color >= colors.size())
++ color = 0;
++ color = colors[color];
++
++ // grab the next character
++ Character *ch = GetCharacter(*pos);
++ if (!ch) continue;
+
+- for (int i = 0; i < 3; i++)
++ if ( alignment & XBFONT_TRUNCATED )
++ {
++ // Check if we will be exceeded the max allowed width
++ if ( cursorX + ch->advance + 3 * m_ellipsesWidth > maxPixelWidth )
+ {
+- RenderCharacter(startX + cursorX, startY, period, color, !scrolling, vertices);
+- cursorX += period->advance;
++ // Yup. Let's draw the ellipses, then bail
++ // Perhaps we should really bail to the next line in this case??
++ Character *period = GetCharacter(L'.');
++ if (!period)
++ break;
++
++ for (int i = 0; i < 3; i++)
++ {
++ RenderCharacter(startX + cursorX, startY, period, color, !scrolling, vertices);
++ cursorX += period->advance;
++ }
++ break;
+ }
+- break;
+ }
+- }
+- else if (maxPixelWidth > 0 && cursorX > maxPixelWidth)
+- break; // exceeded max allowed width - stop rendering
++ else if (maxPixelWidth > 0 && cursorX > maxPixelWidth)
++ break; // exceeded max allowed width - stop rendering
+
+- RenderCharacter(startX + cursorX, startY, ch, color, !scrolling, vertices);
+- if ( alignment & XBFONT_JUSTIFIED )
+- {
+- if ((*pos & 0xffff) == L' ')
+- cursorX += ch->advance + spacePerLetter * justification_word_weight;
++ RenderCharacter(startX + cursorX, startY, ch, color, !scrolling, vertices);
++ if ( alignment & XBFONT_JUSTIFIED )
++ {
++ if ((*pos & 0xffff) == L' ')
++ cursorX += ch->advance + spacePerLetter * justification_word_weight;
++ else
++ cursorX += ch->advance + spacePerLetter;
++ }
+ else
+- cursorX += ch->advance + spacePerLetter;
++ cursorX += ch->advance;
+ }
+- else
+- cursorX += ch->advance;
+ }
++ /* Append the new vertices (from the cache or otherwise) to the set collected
++ * since the first Begin() call */
++ m_vertex.insert(m_vertex.end(), vertices.begin(), vertices.end());
+
+ End();
+ }
+diff --git a/xbmc/guilib/GUIFontTTF.h b/xbmc/guilib/GUIFontTTF.h
+index a5d44f4..3b93672 100644
+--- a/xbmc/guilib/GUIFontTTF.h
++++ b/xbmc/guilib/GUIFontTTF.h
+@@ -66,6 +66,9 @@ struct SVertex
+ };
+
+
++#include "GUIFontCache.h"
++
++
+ class CGUIFontTTFBase
+ {
+ friend class CGUIFont;
+@@ -168,6 +171,8 @@ class CGUIFontTTFBase
+ CStdString m_strFileName;
+ XUTILS::auto_buffer m_fontFileInMemory; // used only in some cases, see CFreeTypeLibrary::GetFont()
+
++ CGUIFontCache m_staticCache;
++
+ private:
+ virtual bool FirstBegin() = 0;
+ virtual void LastEnd() = 0;
+diff --git a/xbmc/guilib/GUIFontTTFGL.cpp b/xbmc/guilib/GUIFontTTFGL.cpp
+index b76c6a5..9935ea4 100644
+--- a/xbmc/guilib/GUIFontTTFGL.cpp
++++ b/xbmc/guilib/GUIFontTTFGL.cpp
+@@ -221,6 +221,7 @@ CBaseTexture* CGUIFontTTFGL::ReallocTexture(unsigned int& newHeight)
+ m_textureScaleX = 1.0f / m_textureWidth;
+ if (m_textureHeight < newHeight)
+ CLog::Log(LOGWARNING, "%s: allocated new texture with height of %d, requested %d", __FUNCTION__, m_textureHeight, newHeight);
++ m_staticCache.Flush();
+
+ memset(newTexture->GetPixels(), 0, m_textureHeight * newTexture->GetPitch());
+ if (m_texture)
+diff --git a/xbmc/guilib/GraphicContext.h b/xbmc/guilib/GraphicContext.h
+index c2a4c16..a385eb4 100644
+--- a/xbmc/guilib/GraphicContext.h
++++ b/xbmc/guilib/GraphicContext.h
+@@ -146,6 +146,7 @@ class CGraphicContext : public CCriticalSection,
+ inline void ScaleFinalCoords(float &x, float &y, float &z) const XBMC_FORCE_INLINE { m_finalTransform.matrix.TransformPosition(x, y, z); }
+ bool RectIsAngled(float x1, float y1, float x2, float y2) const;
+
++ inline const TransformMatrix &GetGUIMatrix() const XBMC_FORCE_INLINE { return m_finalTransform.matrix; }
+ inline float GetGUIScaleX() const XBMC_FORCE_INLINE { return m_finalTransform.scaleX; }
+ inline float GetGUIScaleY() const XBMC_FORCE_INLINE { return m_finalTransform.scaleY; }
+ inline color_t MergeAlpha(color_t color) const XBMC_FORCE_INLINE
+diff --git a/xbmc/guilib/Makefile.in b/xbmc/guilib/Makefile.in
+index 086fb0d..af82979 100644
+--- a/xbmc/guilib/Makefile.in
++++ b/xbmc/guilib/Makefile.in
+@@ -23,6 +23,7 @@ SRCS += GUIEditControl.cpp
+ SRCS += GUIFadeLabelControl.cpp
+ SRCS += GUIFixedListContainer.cpp
+ SRCS += GUIFont.cpp
++SRCS += GUIFontCache.cpp
+ SRCS += GUIFontManager.cpp
+ SRCS += GUIFontTTF.cpp
+ SRCS += GUIImage.cpp
+diff --git a/xbmc/guilib/TransformMatrix.h b/xbmc/guilib/TransformMatrix.h
+index f351c99..9036ba9 100644
+--- a/xbmc/guilib/TransformMatrix.h
++++ b/xbmc/guilib/TransformMatrix.h
+@@ -245,3 +245,14 @@ class TransformMatrix
+ float alpha;
+ bool identity;
+ };
++
++inline bool operator==(const TransformMatrix &a, const TransformMatrix &b)
++{
++ return a.alpha == b.alpha && ((a.identity && b.identity) ||
++ (!a.identity && !b.identity && std::equal(&a.m[0][0], &a.m[0][0] + sizeof a.m / sizeof a.m[0][0], &b.m[0][0])));
++}
++
++inline bool operator!=(const TransformMatrix &a, const TransformMatrix &b)
++{
++ return !operator==(a, b);
++}
+
+From 0ad4af9bc0a131a5f75af68a6f375300a79dc50a Mon Sep 17 00:00:00 2001
+From: Ben Avison
+Date: Thu, 23 Jan 2014 22:24:17 +0000
+Subject: [PATCH 09/61] Lay the groundwork for hardware clipping.
+
+For glScissor() to replace CGraphicContext::ClipRect, a necessary condition
+is that no shear or rotation is introduced between the coordinate systems
+they use; this depends upon the settings of the GUI matrix m_finalTransform
+as well as the OpenGL model-view and projection matrices. These all remain
+unchanged between paired calls of CGUIShader::OnEnabled and
+CGUIShader::OnDisabled, so we scan the matrices in CGUIShader::OnEnabled to
+see whether hardware clipping is possible.
+
+Then, in CGUIFontTTFBase::RenderCharacter, we don't apply software clipping
+in such cases. However, because vertices arising from multiple
+CGUIFontTTFBase::DrawTextInternal calls (each of which often uses a different
+clip rectangle) get lumped into the same vector, which only at the end is
+passed to OpenGL for rendering, we need to wait a few commits before we can
+actually apply hardware clipping. In the meantime, expect to see rendering
+errors.
+---
+ xbmc/guilib/GUIFontTTF.cpp | 3 +-
+ xbmc/guilib/GUIShader.cpp | 80 +++++++++++++++++++++++++++++++-
+ xbmc/guilib/GUIShader.h | 11 +++++
+ xbmc/guilib/GraphicContext.cpp | 10 ++++
+ xbmc/guilib/GraphicContext.h | 1 +
+ xbmc/rendering/RenderSystem.h | 2 +
+ xbmc/rendering/gles/RenderSystemGLES.cpp | 22 +++++++++
+ xbmc/rendering/gles/RenderSystemGLES.h | 2 +
+ 8 files changed, 128 insertions(+), 3 deletions(-)
+
+diff --git a/xbmc/guilib/GUIFontTTF.cpp b/xbmc/guilib/GUIFontTTF.cpp
+index 6a40e9c..a8f5e67 100644
+--- a/xbmc/guilib/GUIFontTTF.cpp
++++ b/xbmc/guilib/GUIFontTTF.cpp
+@@ -734,7 +734,8 @@ void CGUIFontTTFBase::RenderCharacter(float posX, float posY, const Character *c
+ (posY + ch->offsetY + height) * g_graphicsContext.GetGUIScaleY());
+ vertex += CPoint(m_originX, m_originY);
+ CRect texture(ch->left, ch->top, ch->right, ch->bottom);
+- g_graphicsContext.ClipRect(vertex, texture);
++ if (!g_Windowing.ScissorsCanEffectClipping())
++ g_graphicsContext.ClipRect(vertex, texture);
+
+ // transform our positions - note, no scaling due to GUI calibration/resolution occurs
+ float x[4], y[4], z[4];
+diff --git a/xbmc/guilib/GUIShader.cpp b/xbmc/guilib/GUIShader.cpp
+index 23cb84f..5d836cee 100644
+--- a/xbmc/guilib/GUIShader.cpp
++++ b/xbmc/guilib/GUIShader.cpp
+@@ -26,6 +26,8 @@
+ #include "GUIShader.h"
+ #include "MatrixGLES.h"
+ #include "utils/log.h"
++#include "windowing/WindowingFactory.h"
++#include "guilib/GraphicContext.h"
+
+ using namespace Shaders;
+
+@@ -88,8 +90,82 @@ bool CGUIShader::OnEnabled()
+ {
+ // This is called after glUseProgram()
+
+- glUniformMatrix4fv(m_hProj, 1, GL_FALSE, g_matrices.GetMatrix(MM_PROJECTION));
+- glUniformMatrix4fv(m_hModel, 1, GL_FALSE, g_matrices.GetMatrix(MM_MODELVIEW));
++ GLfloat *projMatrix = g_matrices.GetMatrix(MM_PROJECTION);
++ GLfloat *modelMatrix = g_matrices.GetMatrix(MM_MODELVIEW);
++ glUniformMatrix4fv(m_hProj, 1, GL_FALSE, projMatrix);
++ glUniformMatrix4fv(m_hModel, 1, GL_FALSE, modelMatrix);
++
++ const TransformMatrix &guiMatrix = g_graphicsContext.GetGUIMatrix();
++ CRect viewPort; // absolute positions of corners
++ g_Windowing.GetViewPort(viewPort);
++
++ /* glScissor operates in window coordinates. In order that we can use it to
++ * perform clipping, we must ensure that there is an independent linear
++ * transformation from the coordinate system used by CGraphicContext::ClipRect
++ * to window coordinates, separately for X and Y (in other words, no
++ * rotation or shear is introduced at any stage). To do, this, we need to
++ * check that zeros are present in the following locations:
++ *
++ * GUI matrix:
++ * / * 0 * * \
++ * | 0 * * * |
++ * \ 0 0 * * /
++ * ^ TransformMatrix::TransformX/Y/ZCoord are only ever called with
++ * input z = 0, so this column doesn't matter
++ * Model-view matrix:
++ * / * 0 0 * \
++ * | 0 * 0 * |
++ * | 0 0 * * |
++ * \ * * * * / <- eye w has no influence on window x/y (last column below
++ * is either 0 or ignored)
++ * Projection matrix:
++ * / * 0 0 0 \
++ * | 0 * 0 0 |
++ * | * * * * | <- normalised device coordinate z has no influence on window x/y
++ * \ 0 0 * 0 /
++ *
++ * Some of these zeros are not strictly required to ensure this, but they tend
++ * to be zeroed in the common case, so by checking for zeros here, we simplify
++ * the calculation of the window x/y coordinates further down the line.
++ *
++ * (Minor detail: we don't quite deal in window coordinates as defined by
++ * OpenGL, because CRenderSystemGLES::SetScissors flips the Y axis. But all
++ * that's needed to handle that is an effective negation at the stage where
++ * Y is in normalised device coordinates.)
++ */
++ m_clipPossible = guiMatrix.m[0][1] == 0 &&
++ guiMatrix.m[1][0] == 0 &&
++ guiMatrix.m[2][0] == 0 &&
++ guiMatrix.m[2][1] == 0 &&
++ modelMatrix[0+1*4] == 0 &&
++ modelMatrix[0+2*4] == 0 &&
++ modelMatrix[1+0*4] == 0 &&
++ modelMatrix[1+2*4] == 0 &&
++ modelMatrix[2+0*4] == 0 &&
++ modelMatrix[2+1*4] == 0 &&
++ projMatrix[0+1*4] == 0 &&
++ projMatrix[0+2*4] == 0 &&
++ projMatrix[0+3*4] == 0 &&
++ projMatrix[1+0*4] == 0 &&
++ projMatrix[1+2*4] == 0 &&
++ projMatrix[1+3*4] == 0 &&
++ projMatrix[3+0*4] == 0 &&
++ projMatrix[3+1*4] == 0 &&
++ projMatrix[3+3*4] == 0;
++ if (m_clipPossible)
++ {
++ m_clipXFactor = guiMatrix.m[0][0] * modelMatrix[0+0*4] * projMatrix[0+0*4];
++ m_clipXOffset = (guiMatrix.m[0][3] * modelMatrix[0+0*4] + modelMatrix[0+3*4]) * projMatrix[0+0*4];
++ m_clipYFactor = guiMatrix.m[1][1] * modelMatrix[1+1*4] * projMatrix[1+1*4];
++ m_clipYOffset = (guiMatrix.m[1][3] * modelMatrix[1+1*4] + modelMatrix[1+3*4]) * projMatrix[1+1*4];
++ float clipW = (guiMatrix.m[2][3] * modelMatrix[2+2*4] + modelMatrix[2+3*4]) * projMatrix[3+2*4];
++ float xMult = (viewPort.x2 - viewPort.x1) / (2 * clipW);
++ float yMult = (viewPort.y1 - viewPort.y2) / (2 * clipW); // correct for inverted window coordinate scheme
++ m_clipXFactor = m_clipXFactor * xMult;
++ m_clipXOffset = m_clipXOffset * xMult + (viewPort.x2 + viewPort.x1) / 2;
++ m_clipYFactor = m_clipYFactor * yMult;
++ m_clipYOffset = m_clipYOffset * yMult + (viewPort.y2 + viewPort.y1) / 2;
++ }
+
+ return true;
+ }
+diff --git a/xbmc/guilib/GUIShader.h b/xbmc/guilib/GUIShader.h
+index f7b5d9a..fdf7452 100644
+--- a/xbmc/guilib/GUIShader.h
++++ b/xbmc/guilib/GUIShader.h
+@@ -39,6 +39,11 @@ class CGUIShader : public Shaders::CGLSLShaderProgram
+ GLint GetCord1Loc() { return m_hCord1; }
+ GLint GetUniColLoc() { return m_hUniCol; }
+ GLint GetCoord0MatrixLoc() { return m_hCoord0Matrix; }
++ bool HardwareClipIsPossible() { return m_clipPossible; }
++ GLfloat GetClipXFactor() { return m_clipXFactor; }
++ GLfloat GetClipXOffset() { return m_clipXOffset; }
++ GLfloat GetClipYFactor() { return m_clipYFactor; }
++ GLfloat GetClipYOffset() { return m_clipYOffset; }
+
+ protected:
+ GLint m_hTex0;
+@@ -54,6 +59,12 @@ class CGUIShader : public Shaders::CGLSLShaderProgram
+
+ GLfloat *m_proj;
+ GLfloat *m_model;
++
++ bool m_clipPossible;
++ GLfloat m_clipXFactor;
++ GLfloat m_clipXOffset;
++ GLfloat m_clipYFactor;
++ GLfloat m_clipYOffset;
+ };
+
+ #endif // GUI_SHADER_H
+diff --git a/xbmc/guilib/GraphicContext.cpp b/xbmc/guilib/GraphicContext.cpp
+index d40e7a7..3cb5587 100644
+--- a/xbmc/guilib/GraphicContext.cpp
++++ b/xbmc/guilib/GraphicContext.cpp
+@@ -167,6 +167,16 @@ void CGraphicContext::ClipRect(CRect &vertex, CRect &texture, CRect *texture2)
+ }
+ }
+
++CRect CGraphicContext::GetClipRegion()
++{
++ if (m_clipRegions.empty())
++ return CRect(0, 0, m_iScreenWidth, m_iScreenHeight);
++ CRect clipRegion(m_clipRegions.top());
++ if (!m_origins.empty())
++ clipRegion -= m_origins.top();
++ return clipRegion;
++}
++
+ bool CGraphicContext::SetViewPort(float fx, float fy, float fwidth, float fheight, bool intersectPrevious /* = false */)
+ {
+ // transform coordinates - we may have a rotation which changes the positioning of the
+diff --git a/xbmc/guilib/GraphicContext.h b/xbmc/guilib/GraphicContext.h
+index a385eb4..2904c1b 100644
+--- a/xbmc/guilib/GraphicContext.h
++++ b/xbmc/guilib/GraphicContext.h
+@@ -199,6 +199,7 @@ class CGraphicContext : public CCriticalSection,
+ void ApplyHardwareTransform();
+ void RestoreHardwareTransform();
+ void ClipRect(CRect &vertex, CRect &texture, CRect *diffuse = NULL);
++ CRect GetClipRegion();
+ inline void AddGUITransform()
+ {
+ m_transforms.push(m_finalTransform);
+diff --git a/xbmc/rendering/RenderSystem.h b/xbmc/rendering/RenderSystem.h
+index fa64eba..c1dfb93 100644
+--- a/xbmc/rendering/RenderSystem.h
++++ b/xbmc/rendering/RenderSystem.h
+@@ -110,6 +110,8 @@ class CRenderSystemBase
+ virtual void GetViewPort(CRect& viewPort) = 0;
+ virtual void RestoreViewPort() {};
+
++ virtual bool ScissorsCanEffectClipping() { return false; }
++ virtual CRect ClipRectToScissorRect(const CRect &rect) { return CRect(); }
+ virtual void SetScissors(const CRect &rect) = 0;
+ virtual void ResetScissors() = 0;
+
+diff --git a/xbmc/rendering/gles/RenderSystemGLES.cpp b/xbmc/rendering/gles/RenderSystemGLES.cpp
+index 653c9ec..deb3afc 100644
+--- a/xbmc/rendering/gles/RenderSystemGLES.cpp
++++ b/xbmc/rendering/gles/RenderSystemGLES.cpp
+@@ -533,6 +533,28 @@ void CRenderSystemGLES::SetViewPort(CRect& viewPort)
+ m_viewPort[3] = viewPort.Height();
+ }
+
++bool CRenderSystemGLES::ScissorsCanEffectClipping()
++{
++ if (m_pGUIshader[m_method])
++ return m_pGUIshader[m_method]->HardwareClipIsPossible();
++
++ return false;
++}
++
++CRect CRenderSystemGLES::ClipRectToScissorRect(const CRect &rect)
++{
++ if (!m_pGUIshader[m_method])
++ return CRect();
++ float xFactor = m_pGUIshader[m_method]->GetClipXFactor();
++ float xOffset = m_pGUIshader[m_method]->GetClipXOffset();
++ float yFactor = m_pGUIshader[m_method]->GetClipYFactor();
++ float yOffset = m_pGUIshader[m_method]->GetClipYOffset();
++ return CRect(rect.x1 * xFactor + xOffset,
++ rect.y1 * yFactor + yOffset,
++ rect.x2 * xFactor + xOffset,
++ rect.y2 * yFactor + yOffset);
++}
++
+ void CRenderSystemGLES::SetScissors(const CRect &rect)
+ {
+ if (!m_bRenderCreated)
+diff --git a/xbmc/rendering/gles/RenderSystemGLES.h b/xbmc/rendering/gles/RenderSystemGLES.h
+index 98e398a..81ee49e 100644
+--- a/xbmc/rendering/gles/RenderSystemGLES.h
++++ b/xbmc/rendering/gles/RenderSystemGLES.h
+@@ -63,6 +63,8 @@ class CRenderSystemGLES : public CRenderSystemBase
+ virtual void SetViewPort(CRect& viewPort);
+ virtual void GetViewPort(CRect& viewPort);
+
++ virtual bool ScissorsCanEffectClipping();
++ virtual CRect ClipRectToScissorRect(const CRect &rect);
+ virtual void SetScissors(const CRect& rect);
+ virtual void ResetScissors();
+
+
+From e5812aee3483744b42f7c98043261153d2a0ae22 Mon Sep 17 00:00:00 2001
+From: Ben Avison
+Date: Thu, 23 Jan 2014 16:42:22 +0000
+Subject: [PATCH 10/61] Increase font cache hit rate by keying on the
+ fractional part of m_originX and m_originY *after* they have been through the
+ graphics context's transformation matrix, plus the scale/rotation elements of
+ the matrix, rather than the origin in the original frame of reference plus
+ the complete transformation matrix. All vertices of individual glyph bounding
+ boxes are a constant offset from this position, and when the fractional part
+ of the translation is a match, the rounding of each vertex will be in the
+ same direction; this permits us to calculate the desired vertices from the
+ cached ones simply by adding the integer parts of the translations with no
+ additional rounding steps.
+
+Note that this requires that software clipping is *not* performed.
+---
+ xbmc/guilib/GUIFontCache.cpp | 8 +++++++
+ xbmc/guilib/GUIFontCache.h | 43 +++++++++++++++++++++++++++++++++++
+ xbmc/guilib/GUIFontTTF.cpp | 53 +++++++++++++++++++++++++++++++++++---------
+ xbmc/guilib/GUIFontTTF.h | 1 +
+ 4 files changed, 95 insertions(+), 10 deletions(-)
+
+diff --git a/xbmc/guilib/GUIFontCache.cpp b/xbmc/guilib/GUIFontCache.cpp
+index 2c72f9c..df466a5 100644
+--- a/xbmc/guilib/GUIFontCache.cpp
++++ b/xbmc/guilib/GUIFontCache.cpp
+@@ -85,6 +85,9 @@ Value &CGUIFontCache::Lookup(Position &pos,
+ else
+ {
+ /* Cache hit */
++ /* Update the translation arguments so that they hold the offset to apply
++ * to the cached values (but only in the dynamic case) */
++ pos.UpdateWithOffsets(i->m_key.m_pos, scrolling);
+ /* Update time in entry and move to the back of the list */
+ i->m_lastUsedMillis = nowMillis;
+ m_list.template get().relocate(m_list.template get().end(), m_list.template project(i));
+@@ -103,3 +106,8 @@ template void CGUIFontCacheEntry::~CGUIFontCacheEntry();
+ template CGUIFontCacheStaticValue &CGUIFontCache::Lookup(CGUIFontCacheStaticPosition &, const vecColors &, const vecText &, uint32_t, float, bool, unsigned int, bool &);
+ template void CGUIFontCache::Flush();
++
++template void CGUIFontCacheEntry::Reassign::operator()(CGUIFontCacheEntry &entry);
++template CGUIFontCacheEntry::~CGUIFontCacheEntry();
++template CGUIFontCacheDynamicValue &CGUIFontCache::Lookup(CGUIFontCacheDynamicPosition &, const vecColors &, const vecText &, uint32_t, float, bool, unsigned int, bool &);
++template void CGUIFontCache::Flush();
+diff --git a/xbmc/guilib/GUIFontCache.h b/xbmc/guilib/GUIFontCache.h
+index ef65845..d913dee 100644
+--- a/xbmc/guilib/GUIFontCache.h
++++ b/xbmc/guilib/GUIFontCache.h
+@@ -44,6 +44,7 @@
+ using namespace boost::multi_index;
+
+ #define FONT_CACHE_TIME_LIMIT (1000)
++#define FONT_CACHE_DIST_LIMIT (0.01)
+
+ template class CGUIFontCache;
+ class CGUIFontTTFBase;
+@@ -197,6 +198,7 @@ struct CGUIFontCacheStaticPosition
+ float m_x;
+ float m_y;
+ CGUIFontCacheStaticPosition(float x, float y) : m_x(x), m_y(y) {}
++ void UpdateWithOffsets(const CGUIFontCacheStaticPosition &cached, bool scrolling) {}
+ };
+
+ typedef std::vector CGUIFontCacheStaticValue;
+@@ -214,4 +216,45 @@ inline float MatrixHashContribution(const CGUIFontCacheKey CGUIFontCacheDynamicValue;
++
++inline bool Match(const CGUIFontCacheDynamicPosition &a, const TransformMatrix &a_m,
++ const CGUIFontCacheDynamicPosition &b, const TransformMatrix &b_m,
++ bool scrolling)
++{
++ float diffX = a.m_x - b.m_x + FONT_CACHE_DIST_LIMIT;
++ float diffY = a.m_y - b.m_y + FONT_CACHE_DIST_LIMIT;
++ float diffZ = a.m_z - b.m_z + FONT_CACHE_DIST_LIMIT;
++ return (scrolling || diffX - floorf(diffX) < 2 * FONT_CACHE_DIST_LIMIT) &&
++ diffY - floorf(diffY) < 2 * FONT_CACHE_DIST_LIMIT &&
++ diffZ - floorf(diffZ) < 2 * FONT_CACHE_DIST_LIMIT &&
++ a_m.m[0][0] == b_m.m[0][0] &&
++ a_m.m[1][1] == b_m.m[1][1] &&
++ a_m.m[2][2] == b_m.m[2][2];
++ // We already know the first 3 columns of both matrices are diagonal, so no need to check the other elements
++}
++
++inline float MatrixHashContribution(const CGUIFontCacheKey &a)
++{
++ return 0;
++}
++
+ #endif
+diff --git a/xbmc/guilib/GUIFontTTF.cpp b/xbmc/guilib/GUIFontTTF.cpp
+index a8f5e67..91bf91b 100644
+--- a/xbmc/guilib/GUIFontTTF.cpp
++++ b/xbmc/guilib/GUIFontTTF.cpp
+@@ -154,7 +154,7 @@ class CFreeTypeLibrary
+ XBMC_GLOBAL_REF(CFreeTypeLibrary, g_freeTypeLibrary); // our freetype library
+ #define g_freeTypeLibrary XBMC_GLOBAL_USE(CFreeTypeLibrary)
+
+-CGUIFontTTFBase::CGUIFontTTFBase(const CStdString& strFileName) : m_staticCache(*this)
++CGUIFontTTFBase::CGUIFontTTFBase(const CStdString& strFileName) : m_staticCache(*this), m_dynamicCache(*this)
+ {
+ m_texture = NULL;
+ m_char = NULL;
+@@ -356,13 +356,28 @@ void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors
+ Begin();
+
+ bool dirtyCache;
++ bool hardwareClipping = g_Windowing.ScissorsCanEffectClipping();
+ CGUIFontCacheStaticPosition staticPos(x, y);
+- std::vector &vertices = m_staticCache.Lookup(staticPos,
+- colors, text,
+- alignment, maxPixelWidth,
+- scrolling,
+- XbmcThreads::SystemClockMillis(),
+- dirtyCache);
++ CGUIFontCacheDynamicPosition dynamicPos;
++ if (hardwareClipping)
++ {
++ dynamicPos = CGUIFontCacheDynamicPosition(g_graphicsContext.ScaleFinalXCoord(x, y),
++ g_graphicsContext.ScaleFinalYCoord(x, y),
++ g_graphicsContext.ScaleFinalZCoord(x, y));
++ }
++ std::vector &vertices = hardwareClipping ?
++ m_dynamicCache.Lookup(dynamicPos,
++ colors, text,
++ alignment, maxPixelWidth,
++ scrolling,
++ XbmcThreads::SystemClockMillis(),
++ dirtyCache) :
++ m_staticCache.Lookup(staticPos,
++ colors, text,
++ alignment, maxPixelWidth,
++ scrolling,
++ XbmcThreads::SystemClockMillis(),
++ dirtyCache);
+ if (dirtyCache)
+ {
+ // save the origin, which is scaled separately
+@@ -465,10 +480,28 @@ void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors
+ else
+ cursorX += ch->advance;
+ }
++ if (hardwareClipping)
++ /* Append the new vertices (which we have just constructed in the cache)
++ * to the set collected since the first Begin() call */
++ m_vertex.insert(m_vertex.end(), vertices.begin(), vertices.end());
++ }
++ else if (hardwareClipping)
++ {
++ /* Apply the translation offset to the vertices from the cache after
++ * appending them to the set collected since the first Begin() call */
++ m_vertex.insert(m_vertex.end(), vertices.begin(), vertices.end());
++ SVertex *v;
++ for (v = &*m_vertex.end() - vertices.size(); v != &*m_vertex.end(); v++)
++ {
++ v->x += dynamicPos.m_x;
++ v->y += dynamicPos.m_y;
++ v->z += dynamicPos.m_z;
++ }
+ }
+- /* Append the new vertices (from the cache or otherwise) to the set collected
+- * since the first Begin() call */
+- m_vertex.insert(m_vertex.end(), vertices.begin(), vertices.end());
++ if (!hardwareClipping)
++ /* Append the new vertices (from the cache or otherwise) to the set collected
++ * since the first Begin() call */
++ m_vertex.insert(m_vertex.end(), vertices.begin(), vertices.end());
+
+ End();
+ }
+diff --git a/xbmc/guilib/GUIFontTTF.h b/xbmc/guilib/GUIFontTTF.h
+index 3b93672..258dffa 100644
+--- a/xbmc/guilib/GUIFontTTF.h
++++ b/xbmc/guilib/GUIFontTTF.h
+@@ -172,6 +172,7 @@ class CGUIFontTTFBase
+ XUTILS::auto_buffer m_fontFileInMemory; // used only in some cases, see CFreeTypeLibrary::GetFont()
+
+ CGUIFontCache m_staticCache;
++ CGUIFontCache m_dynamicCache;
+
+ private:
+ virtual bool FirstBegin() = 0;
+
+From 34e167b49c1a081d42dd6ebac1011f5776671acc Mon Sep 17 00:00:00 2001
+From: Ben Avison
+Date: Wed, 8 Jan 2014 12:16:33 +0000
+Subject: [PATCH 11/61] Rewrite of scrolling text code.
+
+No longer shuffles the string round to minimise the number of characters
+before the clipping rectangle; this doesn't save much on rendering time but
+does harm the effectiveness of the cache. Now uses a pixel offset into the
+string rather than a character + pixel offset, and plots the entire string
+every time (execpt when the wrap point is visible, in which case the entire
+string is plotted twice).
+
+It also makes motion smoother, because (possibly unintentionally) the
+previous code preferred to align the scroll offset with character boundaries.
+This would lead to uneven changes of position, especially when the width of
+the character currently being scrolled off the edge was only slightly more
+than an integral multiple of the scroll increment.
+---
+ xbmc/guilib/GUIFadeLabelControl.cpp | 8 +--
+ xbmc/guilib/GUIFont.cpp | 123 +++++++++++++-----------------------
+ xbmc/guilib/GUIFont.h | 17 ++---
+ xbmc/guilib/GUIRSSControl.cpp | 6 +-
+ xbmc/utils/RssReader.cpp | 2 +-
+ xbmc/utils/RssReader.h | 2 +-
+ 6 files changed, 58 insertions(+), 100 deletions(-)
+
+diff --git a/xbmc/guilib/GUIFadeLabelControl.cpp b/xbmc/guilib/GUIFadeLabelControl.cpp
+index 844f960..5859d9f 100644
+--- a/xbmc/guilib/GUIFadeLabelControl.cpp
++++ b/xbmc/guilib/GUIFadeLabelControl.cpp
+@@ -109,18 +109,14 @@ void CGUIFadeLabelControl::Process(unsigned int currentTime, CDirtyRegionList &d
+ bool moveToNextLabel = false;
+ if (!m_scrollOut)
+ {
+- vecText text;
+- m_textLayout.GetFirstText(text);
+- if (m_scrollInfo.characterPos && m_scrollInfo.characterPos < text.size())
+- text.erase(text.begin(), text.begin() + min((int)m_scrollInfo.characterPos - 1, (int)text.size()));
+- if (m_label.font->GetTextWidth(text) < m_width)
++ if (m_scrollInfo.pixelPos + m_width > m_scrollInfo.m_textWidth)
+ {
+ if (m_fadeAnim.GetProcess() != ANIM_PROCESS_NORMAL)
+ m_fadeAnim.QueueAnimation(ANIM_PROCESS_NORMAL);
+ moveToNextLabel = true;
+ }
+ }
+- else if (m_scrollInfo.characterPos > m_textLayout.GetTextLength())
++ else if (m_scrollInfo.pixelPos > m_scrollInfo.m_textWidth)
+ moveToNextLabel = true;
+
+ // apply the fading animation
+diff --git a/xbmc/guilib/GUIFont.cpp b/xbmc/guilib/GUIFont.cpp
+index a7ee668..eb8efdb 100644
+--- a/xbmc/guilib/GUIFont.cpp
++++ b/xbmc/guilib/GUIFont.cpp
+@@ -36,7 +36,12 @@ CScrollInfo::CScrollInfo(unsigned int wait /* = 50 */, float pos /* = 0 */,
+ initialWait = wait;
+ initialPos = pos;
+ SetSpeed(speed ? speed : defaultSpeed);
+- g_charsetConverter.utf8ToW(scrollSuffix, suffix);
++ CStdStringW wsuffix;
++ g_charsetConverter.utf8ToW(scrollSuffix, wsuffix);
++ suffix.clear();
++ suffix.reserve(wsuffix.size());
++ for (vecText::size_type i = 0; i < wsuffix.size(); i++)
++ suffix.push_back(wsuffix[i]);
+ Reset();
+ }
+
+@@ -115,11 +120,12 @@ bool CGUIFont::UpdateScrollInfo(const vecText &text, CScrollInfo &scrollInfo)
+ {
+ // draw at our scroll position
+ // we handle the scrolling as follows:
+- // We scroll on a per-pixel basis up until we have scrolled the first character outside
+- // of our viewport, whereby we cycle the string around, and reset the scroll position.
+- //
+- // pixelPos is the amount in pixels to move the string by.
+- // characterPos is the amount in characters to rotate the string by.
++ // We scroll on a per-pixel basis (eschewing the use of character indices
++ // which were also in use previously). The complete string, including suffix,
++ // is plotted to achieve the desired effect - normally just the one time, but
++ // if there is a wrap point within the viewport then it will be plotted twice.
++ // If the string is smaller than the viewport, then it may be plotted even
++ // more times than that.
+ //
+ if (scrollInfo.waitTime)
+ {
+@@ -135,54 +141,19 @@ bool CGUIFont::UpdateScrollInfo(const vecText &text, CScrollInfo &scrollInfo)
+ // move along by the appropriate scroll amount
+ float scrollAmount = fabs(scrollInfo.GetPixelsPerFrame() * g_graphicsContext.GetGUIScaleX());
+
+- if (scrollInfo.pixelSpeed > 0)
++ if (!scrollInfo.m_widthValid)
+ {
+- // we want to move scrollAmount, grab the next character
+- float charWidth = GetCharWidth(scrollInfo.GetCurrentChar(text));
+- if (scrollInfo.pixelPos + scrollAmount < charWidth)
+- scrollInfo.pixelPos += scrollAmount; // within the current character
+- else
+- { // past the current character, decrement scrollAmount by the charWidth and move to the next character
+- while (scrollInfo.pixelPos + scrollAmount >= charWidth)
+- {
+- scrollAmount -= (charWidth - scrollInfo.pixelPos);
+- scrollInfo.pixelPos = 0;
+- scrollInfo.characterPos++;
+- if (scrollInfo.characterPos >= text.size() + scrollInfo.suffix.size())
+- {
+- scrollInfo.Reset();
+- break;
+- }
+- charWidth = GetCharWidth(scrollInfo.GetCurrentChar(text));
+- }
+- }
+- }
+- else if (scrollInfo.pixelSpeed < 0)
+- { // scrolling backwards
+- // we want to move scrollAmount, grab the next character
+- float charWidth = GetCharWidth(scrollInfo.GetCurrentChar(text));
+- if (scrollInfo.pixelPos + scrollAmount < charWidth)
+- scrollInfo.pixelPos += scrollAmount; // within the current character
+- else
+- { // past the current character, decrement scrollAmount by the charWidth and move to the next character
+- while (scrollInfo.pixelPos + scrollAmount >= charWidth)
+- {
+- scrollAmount -= (charWidth - scrollInfo.pixelPos);
+- scrollInfo.pixelPos = 0;
+- if (scrollInfo.characterPos == 0)
+- {
+- scrollInfo.Reset();
+- scrollInfo.characterPos = text.size() + scrollInfo.suffix.size() - 1;
+- break;
+- }
+- scrollInfo.characterPos--;
+- charWidth = GetCharWidth(scrollInfo.GetCurrentChar(text));
+- }
+- }
++ /* Calculate the pixel width of the complete string */
++ scrollInfo.m_textWidth = GetTextWidth(text);
++ scrollInfo.m_totalWidth = scrollInfo.m_textWidth + GetTextWidth(scrollInfo.suffix);
++ scrollInfo.m_widthValid = true;
+ }
++ scrollInfo.pixelPos += scrollAmount;
++ assert(scrollInfo.m_totalWidth != 0);
++ while (scrollInfo.pixelPos >= scrollInfo.m_totalWidth)
++ scrollInfo.pixelPos -= scrollInfo.m_totalWidth;
+
+- if(scrollInfo.characterPos != old.characterPos
+- || scrollInfo.pixelPos != old.pixelPos)
++ if (scrollInfo.pixelPos != old.pixelPos)
+ return true;
+ else
+ return false;
+@@ -194,39 +165,27 @@ void CGUIFont::DrawScrollingText(float x, float y, const vecColors &colors, colo
+ if (!m_font) return;
+ if (!shadowColor) shadowColor = m_shadowColor;
+
+- float spaceWidth = GetCharWidth(L' ');
+- // max chars on screen + extra margin chars
+- vecText::size_type maxChars =
+- std::min(
+- (text.size() + (vecText::size_type)scrollInfo.suffix.size()),
+- (vecText::size_type)((maxWidth * 1.05f) / spaceWidth));
+-
+ if (!text.size() || ClippedRegionIsEmpty(x, y, maxWidth, alignment))
+ return; // nothing to render
+
+- maxWidth = ROUND((maxWidth + scrollInfo.pixelPos) / g_graphicsContext.GetGUIScaleX());
++ if (!scrollInfo.m_widthValid)
++ {
++ /* Calculate the pixel width of the complete string */
++ scrollInfo.m_textWidth = GetTextWidth(text);
++ scrollInfo.m_totalWidth = scrollInfo.m_textWidth + GetTextWidth(scrollInfo.suffix);
++ scrollInfo.m_widthValid = true;
++ }
++
++ assert(scrollInfo.m_totalWidth != 0);
++
++ float textPixelWidth = ROUND(scrollInfo.m_textWidth / g_graphicsContext.GetGUIScaleX());
++ float suffixPixelWidth = ROUND((scrollInfo.m_totalWidth - scrollInfo.m_textWidth) / g_graphicsContext.GetGUIScaleX());
+
+- float charWidth = GetCharWidth(scrollInfo.GetCurrentChar(text));
+ float offset;
+ if(scrollInfo.pixelSpeed >= 0)
+ offset = scrollInfo.pixelPos;
+ else
+- offset = charWidth - scrollInfo.pixelPos;
+-
+- // Now rotate our string as needed, only take a slightly larger then visible part of the text.
+- unsigned int pos = scrollInfo.characterPos;
+- vecText renderText;
+- renderText.reserve(maxChars);
+- for (vecText::size_type i = 0; i < maxChars; i++)
+- {
+- if (pos >= text.size() + scrollInfo.suffix.size())
+- pos = 0;
+- if (pos < text.size())
+- renderText.push_back(text[pos]);
+- else
+- renderText.push_back(scrollInfo.suffix[pos - text.size()]);
+- pos++;
+- }
++ offset = scrollInfo.m_totalWidth - scrollInfo.pixelPos;
+
+ vecColors renderColors;
+ for (unsigned int i = 0; i < colors.size(); i++)
+@@ -239,9 +198,17 @@ void CGUIFont::DrawScrollingText(float x, float y, const vecColors &colors, colo
+ vecColors shadowColors;
+ for (unsigned int i = 0; i < renderColors.size(); i++)
+ shadowColors.push_back((renderColors[i] & 0xff000000) != 0 ? shadowColor : 0);
+- m_font->DrawTextInternal(x - offset + 1, y + 1, shadowColors, renderText, alignment, maxWidth + m_font->GetLineHeight(2.0f), scroll);
++ for (float dx = -offset; dx < maxWidth; dx += scrollInfo.m_totalWidth)
++ {
++ m_font->DrawTextInternal(x + dx + 1, y + 1, shadowColors, text, alignment, textPixelWidth, scroll);
++ m_font->DrawTextInternal(x + dx + scrollInfo.m_textWidth + 1, y + 1, shadowColors, scrollInfo.suffix, alignment, suffixPixelWidth, scroll);
++ }
++ }
++ for (float dx = -offset; dx < maxWidth; dx += scrollInfo.m_totalWidth)
++ {
++ m_font->DrawTextInternal(x + dx, y, renderColors, text, alignment, textPixelWidth, scroll);
++ m_font->DrawTextInternal(x + dx + scrollInfo.m_textWidth, y, renderColors, scrollInfo.suffix, alignment, suffixPixelWidth, scroll);
+ }
+- m_font->DrawTextInternal(x - offset, y, renderColors, renderText, alignment, maxWidth + m_font->GetLineHeight(2.0f), scroll);
+
+ g_graphicsContext.RestoreClipRegion();
+ }
+diff --git a/xbmc/guilib/GUIFont.h b/xbmc/guilib/GUIFont.h
+index c55db48..09cf9b3 100644
+--- a/xbmc/guilib/GUIFont.h
++++ b/xbmc/guilib/GUIFont.h
+@@ -64,7 +64,6 @@ class CScrollInfo
+ void Reset()
+ {
+ waitTime = initialWait;
+- characterPos = 0;
+ // pixelPos is where we start the current letter, so is measured
+ // to the left of the text rendering's left edge. Thus, a negative
+ // value will mean the text starts to the right
+@@ -72,25 +71,19 @@ class CScrollInfo
+ // privates:
+ m_averageFrameTime = 1000.f / abs(defaultSpeed);
+ m_lastFrameTime = 0;
+- }
+- uint32_t GetCurrentChar(const vecText &text) const
+- {
+- assert(text.size());
+- if (characterPos < text.size())
+- return text[characterPos];
+- else if (characterPos < text.size() + suffix.size())
+- return suffix[characterPos - text.size()];
+- return text[0];
++ m_widthValid = false;
+ }
+ float GetPixelsPerFrame();
+
+ float pixelPos;
+ float pixelSpeed;
+ unsigned int waitTime;
+- unsigned int characterPos;
+ unsigned int initialWait;
+ float initialPos;
+- CStdStringW suffix;
++ vecText suffix;
++ mutable float m_textWidth;
++ mutable float m_totalWidth;
++ mutable bool m_widthValid;
+
+ static const int defaultSpeed = 60;
+ private:
+diff --git a/xbmc/guilib/GUIRSSControl.cpp b/xbmc/guilib/GUIRSSControl.cpp
+index 8d985cf..a8e20fc 100644
+--- a/xbmc/guilib/GUIRSSControl.cpp
++++ b/xbmc/guilib/GUIRSSControl.cpp
+@@ -119,7 +119,9 @@ void CGUIRSSControl::Process(unsigned int currentTime, CDirtyRegionList &dirtyre
+ dirty = true;
+
+ if (CRssManager::Get().GetReader(GetID(), GetParentID(), this, m_pReader))
+- m_scrollInfo.characterPos = m_pReader->m_SavedScrollPos;
++ {
++ m_scrollInfo.pixelPos = m_pReader->m_savedScrollPixelPos;
++ }
+ else
+ {
+ if (m_strRSSTags != "")
+@@ -174,7 +176,7 @@ void CGUIRSSControl::Render()
+ if (m_pReader)
+ {
+ m_pReader->CheckForUpdates();
+- m_pReader->m_SavedScrollPos = m_scrollInfo.characterPos;
++ m_pReader->m_savedScrollPixelPos = m_scrollInfo.pixelPos;
+ }
+ }
+ CGUIControl::Render();
+diff --git a/xbmc/utils/RssReader.cpp b/xbmc/utils/RssReader.cpp
+index 5383156..41f9bc2 100644
+--- a/xbmc/utils/RssReader.cpp
++++ b/xbmc/utils/RssReader.cpp
+@@ -55,7 +55,7 @@ CRssReader::CRssReader() : CThread("RSSReader")
+ m_pObserver = NULL;
+ m_spacesBetweenFeeds = 0;
+ m_bIsRunning = false;
+- m_SavedScrollPos = 0;
++ m_savedScrollPixelPos = 0;
+ m_rtlText = false;
+ m_requestRefresh = false;
+ }
+diff --git a/xbmc/utils/RssReader.h b/xbmc/utils/RssReader.h
+index 2cda726..fbc579e 100644
+--- a/xbmc/utils/RssReader.h
++++ b/xbmc/utils/RssReader.h
+@@ -43,7 +43,7 @@ class CRssReader : public CThread
+ void SetObserver(IRssObserver* observer);
+ void CheckForUpdates();
+ void requestRefresh();
+- unsigned int m_SavedScrollPos;
++ float m_savedScrollPixelPos;
+
+ private:
+ void Process();
+
+From f7e99d8c6f5ecbd7eeecf26462d68a8b5e32fbd9 Mon Sep 17 00:00:00 2001
+From: Ben Avison
+Date: Mon, 27 Jan 2014 23:21:10 +0000
+Subject: [PATCH 12/61] Move the application of the translation offsets into
+ the GLES code.
+
+Still all pure software at this stage. Main change is in the data types at
+the interface between CGUIFontTTFBase and CGUIFontTTFGL. The old way
+(array of vertices in m_vertex) are retained in addition, for the sake`of
+cases that need to use software clipping on GLES, as well as for DX and GL
+support where the new scheme is not (yet?) used.
+---
+ xbmc/guilib/GUIFontTTF.cpp | 19 +++---------
+ xbmc/guilib/GUIFontTTF.h | 17 +++++++++++
+ xbmc/guilib/GUIFontTTFGL.cpp | 72 ++++++++++++++++++++++++++++++++------------
+ 3 files changed, 73 insertions(+), 35 deletions(-)
+
+diff --git a/xbmc/guilib/GUIFontTTF.cpp b/xbmc/guilib/GUIFontTTF.cpp
+index 91bf91b..b1d00e5 100644
+--- a/xbmc/guilib/GUIFontTTF.cpp
++++ b/xbmc/guilib/GUIFontTTF.cpp
+@@ -236,6 +236,7 @@ void CGUIFontTTFBase::Clear()
+ g_freeTypeLibrary.ReleaseStroker(m_stroker);
+ m_stroker = NULL;
+
++ m_vertexTrans.clear();
+ m_vertex.clear();
+
+ m_strFileName.clear();
+@@ -334,6 +335,7 @@ void CGUIFontTTFBase::Begin()
+ {
+ if (m_nestedBeginCount == 0 && m_texture != NULL && FirstBegin())
+ {
++ m_vertexTrans.clear();
+ m_vertex.clear();
+ }
+ // Keep track of the nested begin/end calls.
+@@ -481,23 +483,10 @@ void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors
+ cursorX += ch->advance;
+ }
+ if (hardwareClipping)
+- /* Append the new vertices (which we have just constructed in the cache)
+- * to the set collected since the first Begin() call */
+- m_vertex.insert(m_vertex.end(), vertices.begin(), vertices.end());
++ m_vertexTrans.push_back(CTranslatedVertices(0, 0, 0, &vertices));
+ }
+ else if (hardwareClipping)
+- {
+- /* Apply the translation offset to the vertices from the cache after
+- * appending them to the set collected since the first Begin() call */
+- m_vertex.insert(m_vertex.end(), vertices.begin(), vertices.end());
+- SVertex *v;
+- for (v = &*m_vertex.end() - vertices.size(); v != &*m_vertex.end(); v++)
+- {
+- v->x += dynamicPos.m_x;
+- v->y += dynamicPos.m_y;
+- v->z += dynamicPos.m_z;
+- }
+- }
++ m_vertexTrans.push_back(CTranslatedVertices(dynamicPos.m_x, dynamicPos.m_y, dynamicPos.m_z, &vertices));
+ if (!hardwareClipping)
+ /* Append the new vertices (from the cache or otherwise) to the set collected
+ * since the first Begin() call */
+diff --git a/xbmc/guilib/GUIFontTTF.h b/xbmc/guilib/GUIFontTTF.h
+index 258dffa..40bf430 100644
+--- a/xbmc/guilib/GUIFontTTF.h
++++ b/xbmc/guilib/GUIFontTTF.h
+@@ -63,6 +63,14 @@ struct SVertex
+ unsigned char r, g, b, a;
+ #endif
+ float u, v;
++ struct SVertex Offset(float translate[3]) const
++ {
++ SVertex out = *this;
++ out.x += translate[0];
++ out.y += translate[1];
++ out.z += translate[2];
++ return out;
++ }
+ };
+
+
+@@ -161,6 +169,15 @@ class CGUIFontTTFBase
+
+ unsigned int m_nTexture;
+
++ struct CTranslatedVertices
++ {
++ float translateX;
++ float translateY;
++ float translateZ;
++ const std::vector *vertexBuffer;
++ CTranslatedVertices(float translateX, float translateY, float translateZ, const std::vector *vertexBuffer) : translateX(translateX), translateY(translateY), translateZ(translateZ), vertexBuffer(vertexBuffer) {}
++ };
++ std::vector m_vertexTrans;
+ std::vector m_vertex;
+
+ float m_textureScaleX;
+diff --git a/xbmc/guilib/GUIFontTTFGL.cpp b/xbmc/guilib/GUIFontTTFGL.cpp
+index 9935ea4..18c9358 100644
+--- a/xbmc/guilib/GUIFontTTFGL.cpp
++++ b/xbmc/guilib/GUIFontTTFGL.cpp
+@@ -167,34 +167,65 @@ void CGUIFontTTFGL::LastEnd()
+ GLint colLoc = g_Windowing.GUIShaderGetCol();
+ GLint tex0Loc = g_Windowing.GUIShaderGetCoord0();
+
+- // stack object until VBOs will be used
+- std::vector vecVertices( 6 * (m_vertex.size() / 4) );
+- SVertex *vertices = &vecVertices[0];
++ // Enable the attributes used by this shader
++ glEnableVertexAttribArray(posLoc);
++ glEnableVertexAttribArray(colLoc);
++ glEnableVertexAttribArray(tex0Loc);
+
+- for (size_t i=0; i 0)
+ {
+- *vertices++ = m_vertex[i];
+- *vertices++ = m_vertex[i+1];
+- *vertices++ = m_vertex[i+2];
++ // Deal with vertices that had to use software clipping
++ std::vector vecVertices( 6 * (m_vertex.size() / 4) );
++ SVertex *vertices = &vecVertices[0];
+
+- *vertices++ = m_vertex[i+1];
+- *vertices++ = m_vertex[i+3];
+- *vertices++ = m_vertex[i+2];
+- }
++ for (size_t i=0; i 0)
++ {
++ // Deal with the vertices that can be hardware clipped and therefore translated
++ std::vector vecVertices;
++ for (size_t i = 0; i < m_vertexTrans.size(); i++)
++ {
++ float translate[3] = { m_vertexTrans[i].translateX, m_vertexTrans[i].translateY, m_vertexTrans[i].translateZ };
++ for (size_t j = 0; j < m_vertexTrans[i].vertexBuffer->size(); j += 4)
++ {
++ vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j].Offset(translate));
++ vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+1].Offset(translate));
++ vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+2].Offset(translate));
++ vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+1].Offset(translate));
++ vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+3].Offset(translate));
++ vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+2].Offset(translate));
++ }
++ }
++ SVertex *vertices = &vecVertices[0];
+
+- glDrawArrays(GL_TRIANGLES, 0, vecVertices.size());
++ glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, x));
++ // Normalize color values. Does not affect Performance at all.
++ glVertexAttribPointer(colLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, r));
++ glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, u));
++
++ glDrawArrays(GL_TRIANGLES, 0, vecVertices.size());
++ }
+
++ // Disable the attributes used by this shader
+ glDisableVertexAttribArray(posLoc);
+ glDisableVertexAttribArray(colLoc);
+ glDisableVertexAttribArray(tex0Loc);
+@@ -222,6 +253,7 @@ CBaseTexture* CGUIFontTTFGL::ReallocTexture(unsigned int& newHeight)
+ if (m_textureHeight < newHeight)
+ CLog::Log(LOGWARNING, "%s: allocated new texture with height of %d, requested %d", __FUNCTION__, m_textureHeight, newHeight);
+ m_staticCache.Flush();
++ m_dynamicCache.Flush();
+
+ memset(newTexture->GetPixels(), 0, m_textureHeight * newTexture->GetPitch());
+ if (m_texture)
+
+From bf796b3c9edd178fe1fd15b7337045d81a33b3d7 Mon Sep 17 00:00:00 2001
+From: Ben Avison
+Date: Wed, 15 Jan 2014 15:28:06 +0000
+Subject: [PATCH 13/61] Rather than applying the translation offsets to the
+ vertices, now applies them to the model view matrix from the top of the
+ matrix stack and pushes it over to OpenGL. The vertices themselves are still
+ all held client-side.
+
+---
+ xbmc/guilib/GUIFontTTF.h | 8 -------
+ xbmc/guilib/GUIFontTTFGL.cpp | 40 +++++++++++++++++++++-----------
+ xbmc/guilib/GUIShader.h | 1 +
+ xbmc/rendering/gles/RenderSystemGLES.cpp | 8 +++++++
+ xbmc/rendering/gles/RenderSystemGLES.h | 1 +
+ 5 files changed, 36 insertions(+), 22 deletions(-)
+
+diff --git a/xbmc/guilib/GUIFontTTF.h b/xbmc/guilib/GUIFontTTF.h
+index 40bf430..49222a4 100644
+--- a/xbmc/guilib/GUIFontTTF.h
++++ b/xbmc/guilib/GUIFontTTF.h
+@@ -63,14 +63,6 @@ struct SVertex
+ unsigned char r, g, b, a;
+ #endif
+ float u, v;
+- struct SVertex Offset(float translate[3]) const
+- {
+- SVertex out = *this;
+- out.x += translate[0];
+- out.y += translate[1];
+- out.z += translate[2];
+- return out;
+- }
+ };
+
+
+diff --git a/xbmc/guilib/GUIFontTTFGL.cpp b/xbmc/guilib/GUIFontTTFGL.cpp
+index 18c9358..ea08bf4 100644
+--- a/xbmc/guilib/GUIFontTTFGL.cpp
++++ b/xbmc/guilib/GUIFontTTFGL.cpp
+@@ -29,6 +29,7 @@
+ #include "utils/log.h"
+ #include "utils/GLUtils.h"
+ #include "windowing/WindowingFactory.h"
++#include "guilib/MatrixGLES.h"
+
+ // stuff for freetype
+ #include
+@@ -166,6 +167,7 @@ void CGUIFontTTFGL::LastEnd()
+ GLint posLoc = g_Windowing.GUIShaderGetPos();
+ GLint colLoc = g_Windowing.GUIShaderGetCol();
+ GLint tex0Loc = g_Windowing.GUIShaderGetCoord0();
++ GLint modelLoc = g_Windowing.GUIShaderGetModel();
+
+ // Enable the attributes used by this shader
+ glEnableVertexAttribArray(posLoc);
+@@ -204,25 +206,35 @@ void CGUIFontTTFGL::LastEnd()
+ std::vector vecVertices;
+ for (size_t i = 0; i < m_vertexTrans.size(); i++)
+ {
+- float translate[3] = { m_vertexTrans[i].translateX, m_vertexTrans[i].translateY, m_vertexTrans[i].translateZ };
++ // Apply the translation to the currently active (top-of-stack) model view matrix
++ g_matrices.MatrixMode(MM_MODELVIEW);
++ g_matrices.PushMatrix();
++ g_matrices.Translatef(m_vertexTrans[i].translateX, m_vertexTrans[i].translateY, m_vertexTrans[i].translateZ);
++ glUniformMatrix4fv(modelLoc, 1, GL_FALSE, g_matrices.GetMatrix(MM_MODELVIEW));
++
++ vecVertices.clear();
+ for (size_t j = 0; j < m_vertexTrans[i].vertexBuffer->size(); j += 4)
+ {
+- vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j].Offset(translate));
+- vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+1].Offset(translate));
+- vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+2].Offset(translate));
+- vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+1].Offset(translate));
+- vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+3].Offset(translate));
+- vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+2].Offset(translate));
++ vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j]);
++ vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+1]);
++ vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+2]);
++ vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+1]);
++ vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+3]);
++ vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+2]);
+ }
+- }
+- SVertex *vertices = &vecVertices[0];
++ SVertex *vertices = &vecVertices[0];
+
+- glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, x));
+- // Normalize color values. Does not affect Performance at all.
+- glVertexAttribPointer(colLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, r));
+- glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, u));
++ glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, x));
++ // Normalize color values. Does not affect Performance at all.
++ glVertexAttribPointer(colLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, r));
++ glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, u));
+
+- glDrawArrays(GL_TRIANGLES, 0, vecVertices.size());
++ glDrawArrays(GL_TRIANGLES, 0, vecVertices.size());
++
++ g_matrices.PopMatrix();
++ }
++ // Restore the original model view matrix
++ glUniformMatrix4fv(modelLoc, 1, GL_FALSE, g_matrices.GetMatrix(MM_MODELVIEW));
+ }
+
+ // Disable the attributes used by this shader
+diff --git a/xbmc/guilib/GUIShader.h b/xbmc/guilib/GUIShader.h
+index fdf7452..abbe21c 100644
+--- a/xbmc/guilib/GUIShader.h
++++ b/xbmc/guilib/GUIShader.h
+@@ -39,6 +39,7 @@ class CGUIShader : public Shaders::CGLSLShaderProgram
+ GLint GetCord1Loc() { return m_hCord1; }
+ GLint GetUniColLoc() { return m_hUniCol; }
+ GLint GetCoord0MatrixLoc() { return m_hCoord0Matrix; }
++ GLint GetModelLoc() { return m_hModel; }
+ bool HardwareClipIsPossible() { return m_clipPossible; }
+ GLfloat GetClipXFactor() { return m_clipXFactor; }
+ GLfloat GetClipXOffset() { return m_clipXOffset; }
+diff --git a/xbmc/rendering/gles/RenderSystemGLES.cpp b/xbmc/rendering/gles/RenderSystemGLES.cpp
+index deb3afc..0904d1f 100644
+--- a/xbmc/rendering/gles/RenderSystemGLES.cpp
++++ b/xbmc/rendering/gles/RenderSystemGLES.cpp
+@@ -691,4 +691,12 @@ bool CRenderSystemGLES::SupportsStereo(RENDER_STEREO_MODE mode)
+ }
+ }
+
++GLint CRenderSystemGLES::GUIShaderGetModel()
++{
++ if (m_pGUIshader[m_method])
++ return m_pGUIshader[m_method]->GetModelLoc();
++
++ return -1;
++}
++
+ #endif
+diff --git a/xbmc/rendering/gles/RenderSystemGLES.h b/xbmc/rendering/gles/RenderSystemGLES.h
+index 81ee49e..d2f9cd1 100644
+--- a/xbmc/rendering/gles/RenderSystemGLES.h
++++ b/xbmc/rendering/gles/RenderSystemGLES.h
+@@ -91,6 +91,7 @@ class CRenderSystemGLES : public CRenderSystemBase
+ GLint GUIShaderGetCoord1();
+ GLint GUIShaderGetUniCol();
+ GLint GUIShaderGetCoord0Matrix();
++ GLint GUIShaderGetModel();
+
+ protected:
+ virtual void SetVSyncImpl(bool enable) = 0;
+
+From 504eab137cb13388fe90c71594984572196643d7 Mon Sep 17 00:00:00 2001
+From: Ben Avison
+Date: Wed, 29 Jan 2014 13:21:19 +0000
+Subject: [PATCH 14/61] Enable hardware clipping.
+
+---
+ xbmc/guilib/GUIFontTTF.cpp | 4 ++--
+ xbmc/guilib/GUIFontTTF.h | 4 +++-
+ xbmc/guilib/GUIFontTTFGL.cpp | 6 ++++++
+ 3 files changed, 11 insertions(+), 3 deletions(-)
+
+diff --git a/xbmc/guilib/GUIFontTTF.cpp b/xbmc/guilib/GUIFontTTF.cpp
+index b1d00e5..ff51c89 100644
+--- a/xbmc/guilib/GUIFontTTF.cpp
++++ b/xbmc/guilib/GUIFontTTF.cpp
+@@ -483,10 +483,10 @@ void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors
+ cursorX += ch->advance;
+ }
+ if (hardwareClipping)
+- m_vertexTrans.push_back(CTranslatedVertices(0, 0, 0, &vertices));
++ m_vertexTrans.push_back(CTranslatedVertices(0, 0, 0, &vertices, g_graphicsContext.GetClipRegion()));
+ }
+ else if (hardwareClipping)
+- m_vertexTrans.push_back(CTranslatedVertices(dynamicPos.m_x, dynamicPos.m_y, dynamicPos.m_z, &vertices));
++ m_vertexTrans.push_back(CTranslatedVertices(dynamicPos.m_x, dynamicPos.m_y, dynamicPos.m_z, &vertices, g_graphicsContext.GetClipRegion()));
+ if (!hardwareClipping)
+ /* Append the new vertices (from the cache or otherwise) to the set collected
+ * since the first Begin() call */
+diff --git a/xbmc/guilib/GUIFontTTF.h b/xbmc/guilib/GUIFontTTF.h
+index 49222a4..77b324f 100644
+--- a/xbmc/guilib/GUIFontTTF.h
++++ b/xbmc/guilib/GUIFontTTF.h
+@@ -28,6 +28,7 @@
+ */
+
+ #include "utils/auto_buffer.h"
++#include "Geometry.h"
+
+ // forward definition
+ class CBaseTexture;
+@@ -167,7 +168,8 @@ class CGUIFontTTFBase
+ float translateY;
+ float translateZ;
+ const std::vector *vertexBuffer;
+- CTranslatedVertices(float translateX, float translateY, float translateZ, const std::vector *vertexBuffer) : translateX(translateX), translateY(translateY), translateZ(translateZ), vertexBuffer(vertexBuffer) {}
++ CRect clip;
++ CTranslatedVertices(float translateX, float translateY, float translateZ, const std::vector *vertexBuffer, const CRect &clip) : translateX(translateX), translateY(translateY), translateZ(translateZ), vertexBuffer(vertexBuffer), clip(clip) {}
+ };
+ std::vector m_vertexTrans;
+ std::vector m_vertex;
+diff --git a/xbmc/guilib/GUIFontTTFGL.cpp b/xbmc/guilib/GUIFontTTFGL.cpp
+index ea08bf4..b63e337 100644
+--- a/xbmc/guilib/GUIFontTTFGL.cpp
++++ b/xbmc/guilib/GUIFontTTFGL.cpp
+@@ -206,6 +206,10 @@ void CGUIFontTTFGL::LastEnd()
+ std::vector vecVertices;
+ for (size_t i = 0; i < m_vertexTrans.size(); i++)
+ {
++ // Apply the clip rectangle
++ CRect clip = g_Windowing.ClipRectToScissorRect(m_vertexTrans[i].clip);
++ g_Windowing.SetScissors(clip);
++
+ // Apply the translation to the currently active (top-of-stack) model view matrix
+ g_matrices.MatrixMode(MM_MODELVIEW);
+ g_matrices.PushMatrix();
+@@ -233,6 +237,8 @@ void CGUIFontTTFGL::LastEnd()
+
+ g_matrices.PopMatrix();
+ }
++ // Restore the original scissor rectangle
++ g_Windowing.ResetScissors();
+ // Restore the original model view matrix
+ glUniformMatrix4fv(modelLoc, 1, GL_FALSE, g_matrices.GetMatrix(MM_MODELVIEW));
+ }
+
+From 17d9d1abffa0331f5010448e292d8e1fb2bdc3a4 Mon Sep 17 00:00:00 2001
+From: Ben Avison
+Date: Wed, 15 Jan 2014 15:32:51 +0000
+Subject: [PATCH 15/61] Move the vertex data across to a vertex buffer object
+ just prior to drawing.
+
+---
+ xbmc/guilib/GUIFontTTFGL.cpp | 24 +++++++++++++++++++-----
+ 1 file changed, 19 insertions(+), 5 deletions(-)
+
+diff --git a/xbmc/guilib/GUIFontTTFGL.cpp b/xbmc/guilib/GUIFontTTFGL.cpp
+index b63e337..b00055d 100644
+--- a/xbmc/guilib/GUIFontTTFGL.cpp
++++ b/xbmc/guilib/GUIFontTTFGL.cpp
+@@ -228,12 +228,24 @@ void CGUIFontTTFGL::LastEnd()
+ }
+ SVertex *vertices = &vecVertices[0];
+
+- glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, x));
+- // Normalize color values. Does not affect Performance at all.
+- glVertexAttribPointer(colLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, r));
+- glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, u));
+-
++ // Generate a unique buffer object name and put it in vertexBuffer
++ GLuint vertexBuffer;
++ glGenBuffers(1, &vertexBuffer);
++ // Bind the buffer to the OpenGL context's GL_ARRAY_BUFFER binding point
++ glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
++ // Create a data store for the buffer object bound to the GL_ARRAY_BUFFER
++ // binding point (i.e. our buffer object) and initialise it from the
++ // specified client-side pointer
++ glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof *vertices, vertices, GL_STATIC_DRAW);
++ // Set up the offsets of the various vertex attributes within the buffer
++ // object bound to GL_ARRAY_BUFFER
++ glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (GLvoid *) offsetof(SVertex, x));
++ glVertexAttribPointer(colLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(SVertex), (GLvoid *) offsetof(SVertex, r));
++ glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), (GLvoid *) offsetof(SVertex, u));
++ // Do the actual drawing operation, using the full set of vertices in the buffer
+ glDrawArrays(GL_TRIANGLES, 0, vecVertices.size());
++ // Release the buffer name for reuse
++ glDeleteBuffers(1, &vertexBuffer);
+
+ g_matrices.PopMatrix();
+ }
+@@ -241,6 +253,8 @@ void CGUIFontTTFGL::LastEnd()
+ g_Windowing.ResetScissors();
+ // Restore the original model view matrix
+ glUniformMatrix4fv(modelLoc, 1, GL_FALSE, g_matrices.GetMatrix(MM_MODELVIEW));
++ // Unbind GL_ARRAY_BUFFER
++ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ }
+
+ // Disable the attributes used by this shader
+
+From d5e6a10622a0ef375feaed609a37b02e1facd3ba Mon Sep 17 00:00:00 2001
+From: Ben Avison
+Date: Wed, 15 Jan 2014 16:04:04 +0000
+Subject: [PATCH 16/61] Move vertex data into an OpenGL VBO when the font cache
+ entry is populated.
+
+The font cache now stores the "name" (handle) of the VBO, rather than a vector
+of vertices.
+---
+ xbmc/guilib/GUIFontCache.cpp | 6 ++++
+ xbmc/guilib/GUIFontCache.h | 30 +++++++++++++++++-
+ xbmc/guilib/GUIFontTTF.cpp | 15 +++++++--
+ xbmc/guilib/GUIFontTTF.h | 7 +++--
+ xbmc/guilib/GUIFontTTFGL.cpp | 74 ++++++++++++++++++++++++++++++--------------
+ xbmc/guilib/GUIFontTTFGL.h | 5 +++
+ 6 files changed, 107 insertions(+), 30 deletions(-)
+
+diff --git a/xbmc/guilib/GUIFontCache.cpp b/xbmc/guilib/GUIFontCache.cpp
+index df466a5..bd84b9a 100644
+--- a/xbmc/guilib/GUIFontCache.cpp
++++ b/xbmc/guilib/GUIFontCache.cpp
+@@ -111,3 +111,9 @@ template void CGUIFontCacheEntry::~CGUIFontCacheEntry();
+ template CGUIFontCacheDynamicValue &CGUIFontCache::Lookup(CGUIFontCacheDynamicPosition &, const vecColors &, const vecText &, uint32_t, float, bool, unsigned int, bool &);
+ template void CGUIFontCache::Flush();
++
++void CVertexBuffer::clear()
++{
++ if (m_font != NULL)
++ m_font->DestroyVertexBuffer(*this);
++}
+diff --git a/xbmc/guilib/GUIFontCache.h b/xbmc/guilib/GUIFontCache.h
+index d913dee..ff766bf 100644
+--- a/xbmc/guilib/GUIFontCache.h
++++ b/xbmc/guilib/GUIFontCache.h
+@@ -234,7 +234,35 @@ struct CGUIFontCacheDynamicPosition
+ }
+ };
+
+-typedef std::vector CGUIFontCacheDynamicValue;
++struct CVertexBuffer
++{
++ void *bufferHandle;
++ size_t size;
++ CVertexBuffer() : bufferHandle(NULL), size(0), m_font(NULL) {}
++ CVertexBuffer(void *bufferHandle, size_t size, const CGUIFontTTFBase *font) : bufferHandle(bufferHandle), size(size), m_font(font) {}
++ CVertexBuffer(const CVertexBuffer &other) : bufferHandle(other.bufferHandle), size(other.size), m_font(other.m_font)
++ {
++ /* In practice, the copy constructor is only called before a vertex buffer
++ * has been attached. If this should ever change, we'll need another support
++ * function in GUIFontTTFGL/DX to duplicate a buffer, given its handle. */
++ assert(other.bufferHandle == 0);
++ }
++ CVertexBuffer &operator=(CVertexBuffer &other)
++ {
++ /* This is used with move-assignment semantics for initialising the object in the font cache */
++ assert(bufferHandle == 0);
++ bufferHandle = other.bufferHandle;
++ other.bufferHandle = 0;
++ size = other.size;
++ m_font = other.m_font;
++ return *this;
++ }
++ void clear();
++private:
++ const CGUIFontTTFBase *m_font;
++};
++
++typedef CVertexBuffer CGUIFontCacheDynamicValue;
+
+ inline bool Match(const CGUIFontCacheDynamicPosition &a, const TransformMatrix &a_m,
+ const CGUIFontCacheDynamicPosition &b, const TransformMatrix &b_m,
+diff --git a/xbmc/guilib/GUIFontTTF.cpp b/xbmc/guilib/GUIFontTTF.cpp
+index ff51c89..7d4fc88 100644
+--- a/xbmc/guilib/GUIFontTTF.cpp
++++ b/xbmc/guilib/GUIFontTTF.cpp
+@@ -367,13 +367,18 @@ void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors
+ g_graphicsContext.ScaleFinalYCoord(x, y),
+ g_graphicsContext.ScaleFinalZCoord(x, y));
+ }
+- std::vector &vertices = hardwareClipping ?
++ CVertexBuffer unusedVertexBuffer;
++ CVertexBuffer &vertexBuffer = hardwareClipping ?
+ m_dynamicCache.Lookup(dynamicPos,
+ colors, text,
+ alignment, maxPixelWidth,
+ scrolling,
+ XbmcThreads::SystemClockMillis(),
+ dirtyCache) :
++ unusedVertexBuffer;
++ std::vector tempVertices;
++ std::vector &vertices = hardwareClipping ?
++ tempVertices :
+ m_staticCache.Lookup(staticPos,
+ colors, text,
+ alignment, maxPixelWidth,
+@@ -483,10 +488,14 @@ void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors
+ cursorX += ch->advance;
+ }
+ if (hardwareClipping)
+- m_vertexTrans.push_back(CTranslatedVertices(0, 0, 0, &vertices, g_graphicsContext.GetClipRegion()));
++ {
++ CVertexBuffer newVertexBuffer = CreateVertexBuffer(tempVertices);
++ vertexBuffer = newVertexBuffer;
++ m_vertexTrans.push_back(CTranslatedVertices(0, 0, 0, &vertexBuffer, g_graphicsContext.GetClipRegion()));
++ }
+ }
+ else if (hardwareClipping)
+- m_vertexTrans.push_back(CTranslatedVertices(dynamicPos.m_x, dynamicPos.m_y, dynamicPos.m_z, &vertices, g_graphicsContext.GetClipRegion()));
++ m_vertexTrans.push_back(CTranslatedVertices(dynamicPos.m_x, dynamicPos.m_y, dynamicPos.m_z, &vertexBuffer, g_graphicsContext.GetClipRegion()));
+ if (!hardwareClipping)
+ /* Append the new vertices (from the cache or otherwise) to the set collected
+ * since the first Begin() call */
+diff --git a/xbmc/guilib/GUIFontTTF.h b/xbmc/guilib/GUIFontTTF.h
+index 77b324f..caa1e62 100644
+--- a/xbmc/guilib/GUIFontTTF.h
++++ b/xbmc/guilib/GUIFontTTF.h
+@@ -85,6 +85,9 @@ class CGUIFontTTFBase
+
+ void Begin();
+ void End();
++ /* The next two should only be called if we've declared we can do hardware clipping */
++ virtual CVertexBuffer CreateVertexBuffer(const std::vector &vertices) const { assert(false); return CVertexBuffer(); }
++ virtual void DestroyVertexBuffer(CVertexBuffer &bufferHandle) const {}
+
+ const CStdString& GetFileName() const { return m_strFileName; };
+
+@@ -167,9 +170,9 @@ class CGUIFontTTFBase
+ float translateX;
+ float translateY;
+ float translateZ;
+- const std::vector *vertexBuffer;
++ const CVertexBuffer *vertexBuffer;
+ CRect clip;
+- CTranslatedVertices(float translateX, float translateY, float translateZ, const std::vector *vertexBuffer, const CRect &clip) : translateX(translateX), translateY(translateY), translateZ(translateZ), vertexBuffer(vertexBuffer), clip(clip) {}
++ CTranslatedVertices(float translateX, float translateY, float translateZ, const CVertexBuffer *vertexBuffer, const CRect &clip) : translateX(translateX), translateY(translateY), translateZ(translateZ), vertexBuffer(vertexBuffer), clip(clip) {}
+ };
+ std::vector m_vertexTrans;
+ std::vector m_vertex;
+diff --git a/xbmc/guilib/GUIFontTTFGL.cpp b/xbmc/guilib/GUIFontTTFGL.cpp
+index b00055d..aabb9a6 100644
+--- a/xbmc/guilib/GUIFontTTFGL.cpp
++++ b/xbmc/guilib/GUIFontTTFGL.cpp
+@@ -52,6 +52,10 @@ CGUIFontTTFGL::CGUIFontTTFGL(const CStdString& strFileName)
+
+ CGUIFontTTFGL::~CGUIFontTTFGL(void)
+ {
++ // It's important that all the CGUIFontCacheEntry objects are
++ // destructed before the CGUIFontTTFGL goes out of scope, because
++ // our virtual methods won't be accessible after this point
++ m_dynamicCache.Flush();
+ }
+
+ bool CGUIFontTTFGL::FirstBegin()
+@@ -203,7 +207,6 @@ void CGUIFontTTFGL::LastEnd()
+ if (m_vertexTrans.size() > 0)
+ {
+ // Deal with the vertices that can be hardware clipped and therefore translated
+- std::vector vecVertices;
+ for (size_t i = 0; i < m_vertexTrans.size(); i++)
+ {
+ // Apply the clip rectangle
+@@ -216,36 +219,17 @@ void CGUIFontTTFGL::LastEnd()
+ g_matrices.Translatef(m_vertexTrans[i].translateX, m_vertexTrans[i].translateY, m_vertexTrans[i].translateZ);
+ glUniformMatrix4fv(modelLoc, 1, GL_FALSE, g_matrices.GetMatrix(MM_MODELVIEW));
+
+- vecVertices.clear();
+- for (size_t j = 0; j < m_vertexTrans[i].vertexBuffer->size(); j += 4)
+- {
+- vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j]);
+- vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+1]);
+- vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+2]);
+- vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+1]);
+- vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+3]);
+- vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+2]);
+- }
+- SVertex *vertices = &vecVertices[0];
+-
+- // Generate a unique buffer object name and put it in vertexBuffer
+- GLuint vertexBuffer;
+- glGenBuffers(1, &vertexBuffer);
+ // Bind the buffer to the OpenGL context's GL_ARRAY_BUFFER binding point
+- glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
+- // Create a data store for the buffer object bound to the GL_ARRAY_BUFFER
+- // binding point (i.e. our buffer object) and initialise it from the
+- // specified client-side pointer
+- glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof *vertices, vertices, GL_STATIC_DRAW);
++ glBindBuffer(GL_ARRAY_BUFFER, (GLuint) m_vertexTrans[i].vertexBuffer->bufferHandle);
++
+ // Set up the offsets of the various vertex attributes within the buffer
+ // object bound to GL_ARRAY_BUFFER
+ glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (GLvoid *) offsetof(SVertex, x));
+ glVertexAttribPointer(colLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(SVertex), (GLvoid *) offsetof(SVertex, r));
+ glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), (GLvoid *) offsetof(SVertex, u));
++
+ // Do the actual drawing operation, using the full set of vertices in the buffer
+- glDrawArrays(GL_TRIANGLES, 0, vecVertices.size());
+- // Release the buffer name for reuse
+- glDeleteBuffers(1, &vertexBuffer);
++ glDrawArrays(GL_TRIANGLES, 0, 6 * m_vertexTrans[i].vertexBuffer->size);
+
+ g_matrices.PopMatrix();
+ }
+@@ -266,6 +250,48 @@ void CGUIFontTTFGL::LastEnd()
+ #endif
+ }
+
++#if HAS_GLES
++CVertexBuffer CGUIFontTTFGL::CreateVertexBuffer(const std::vector &vertices) const
++{
++ // Rearrange the vertices to describe triangles
++ std::vector triangleVertices;
++ triangleVertices.reserve(vertices.size() * 6 / 4);
++ for (size_t i = 0; i < vertices.size(); i += 4)
++ {
++ triangleVertices.push_back(vertices[i]);
++ triangleVertices.push_back(vertices[i+1]);
++ triangleVertices.push_back(vertices[i+2]);
++ triangleVertices.push_back(vertices[i+1]);
++ triangleVertices.push_back(vertices[i+3]);
++ triangleVertices.push_back(vertices[i+2]);
++ }
++
++ // Generate a unique buffer object name and put it in bufferHandle
++ GLuint bufferHandle;
++ glGenBuffers(1, &bufferHandle);
++ // Bind the buffer to the OpenGL context's GL_ARRAY_BUFFER binding point
++ glBindBuffer(GL_ARRAY_BUFFER, bufferHandle);
++ // Create a data store for the buffer object bound to the GL_ARRAY_BUFFER
++ // binding point (i.e. our buffer object) and initialise it from the
++ // specified client-side pointer
++ glBufferData(GL_ARRAY_BUFFER, triangleVertices.size() * sizeof (SVertex), &triangleVertices[0], GL_STATIC_DRAW);
++ // Unbind GL_ARRAY_BUFFER
++ glBindBuffer(GL_ARRAY_BUFFER, 0);
++
++ return CVertexBuffer((void *) bufferHandle, vertices.size() / 4, this);
++}
++
++void CGUIFontTTFGL::DestroyVertexBuffer(CVertexBuffer &buffer) const
++{
++ if (buffer.bufferHandle != 0)
++ {
++ // Release the buffer name for reuse
++ glDeleteBuffers(1, (GLuint *) &buffer.bufferHandle);
++ buffer.bufferHandle = 0;
++ }
++}
++#endif
++
+ CBaseTexture* CGUIFontTTFGL::ReallocTexture(unsigned int& newHeight)
+ {
+ newHeight = CBaseTexture::PadPow2(newHeight);
+diff --git a/xbmc/guilib/GUIFontTTFGL.h b/xbmc/guilib/GUIFontTTFGL.h
+index 735fb3a..6102c90 100644
+--- a/xbmc/guilib/GUIFontTTFGL.h
++++ b/xbmc/guilib/GUIFontTTFGL.h
+@@ -29,6 +29,7 @@
+
+
+ #include "GUIFontTTF.h"
++#include "system.h"
+
+
+ /*!
+@@ -43,6 +44,10 @@ class CGUIFontTTFGL : public CGUIFontTTFBase
+
+ virtual bool FirstBegin();
+ virtual void LastEnd();
++#if HAS_GLES
++ virtual CVertexBuffer CreateVertexBuffer(const std::vector &vertices) const;
++ virtual void DestroyVertexBuffer(CVertexBuffer &bufferHandle) const;
++#endif
+
+ protected:
+ virtual CBaseTexture* ReallocTexture(unsigned int& newHeight);
+
+From af7b182e5e871b1e478917973d7b06836172cba1 Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Sat, 1 Nov 2014 22:15:13 +0000
+Subject: [PATCH 17/61] Switch from glDrawArrays() to glDrawElements().
+
+This involves setting up a static VBO containing the indexes necessary to
+convert from quads to triangles on the fly in the GPU.
+---
+ xbmc/guilib/GUIFontTTFGL.cpp | 72 +++++++++++++++++++++++++------------
+ xbmc/guilib/GUIFontTTFGL.h | 11 +++++-
+ xbmc/windowing/egl/WinSystemEGL.cpp | 17 +++++++++
+ 3 files changed, 77 insertions(+), 23 deletions(-)
+
+diff --git a/xbmc/guilib/GUIFontTTFGL.cpp b/xbmc/guilib/GUIFontTTFGL.cpp
+index aabb9a6..812662c 100644
+--- a/xbmc/guilib/GUIFontTTFGL.cpp
++++ b/xbmc/guilib/GUIFontTTFGL.cpp
+@@ -207,6 +207,10 @@ void CGUIFontTTFGL::LastEnd()
+ if (m_vertexTrans.size() > 0)
+ {
+ // Deal with the vertices that can be hardware clipped and therefore translated
++
++ // Bind our pre-calculated array to GL_ELEMENT_ARRAY_BUFFER
++ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementArrayHandle);
++
+ for (size_t i = 0; i < m_vertexTrans.size(); i++)
+ {
+ // Apply the clip rectangle
+@@ -222,14 +226,21 @@ void CGUIFontTTFGL::LastEnd()
+ // Bind the buffer to the OpenGL context's GL_ARRAY_BUFFER binding point
+ glBindBuffer(GL_ARRAY_BUFFER, (GLuint) m_vertexTrans[i].vertexBuffer->bufferHandle);
+
+- // Set up the offsets of the various vertex attributes within the buffer
+- // object bound to GL_ARRAY_BUFFER
+- glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (GLvoid *) offsetof(SVertex, x));
+- glVertexAttribPointer(colLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(SVertex), (GLvoid *) offsetof(SVertex, r));
+- glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), (GLvoid *) offsetof(SVertex, u));
++ // Do the actual drawing operation, split into groups of characters no
++ // larger than the pre-determined size of the element array
++ for (size_t character = 0; m_vertexTrans[i].vertexBuffer->size > character; character += ELEMENT_ARRAY_MAX_CHAR_INDEX)
++ {
++ size_t count = m_vertexTrans[i].vertexBuffer->size - character;
++ count = std::min(count, ELEMENT_ARRAY_MAX_CHAR_INDEX);
++
++ // Set up the offsets of the various vertex attributes within the buffer
++ // object bound to GL_ARRAY_BUFFER
++ glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (GLvoid *) (character*sizeof(SVertex)*4 + offsetof(SVertex, x)));
++ glVertexAttribPointer(colLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(SVertex), (GLvoid *) (character*sizeof(SVertex)*4 + offsetof(SVertex, r)));
++ glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), (GLvoid *) (character*sizeof(SVertex)*4 + offsetof(SVertex, u)));
+
+- // Do the actual drawing operation, using the full set of vertices in the buffer
+- glDrawArrays(GL_TRIANGLES, 0, 6 * m_vertexTrans[i].vertexBuffer->size);
++ glDrawElements(GL_TRIANGLES, 6 * count, GL_UNSIGNED_SHORT, 0);
++ }
+
+ g_matrices.PopMatrix();
+ }
+@@ -237,8 +248,9 @@ void CGUIFontTTFGL::LastEnd()
+ g_Windowing.ResetScissors();
+ // Restore the original model view matrix
+ glUniformMatrix4fv(modelLoc, 1, GL_FALSE, g_matrices.GetMatrix(MM_MODELVIEW));
+- // Unbind GL_ARRAY_BUFFER
++ // Unbind GL_ARRAY_BUFFER and GL_ELEMENT_ARRAY_BUFFER
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
++ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ }
+
+ // Disable the attributes used by this shader
+@@ -253,19 +265,6 @@ void CGUIFontTTFGL::LastEnd()
+ #if HAS_GLES
+ CVertexBuffer CGUIFontTTFGL::CreateVertexBuffer(const std::vector &vertices) const
+ {
+- // Rearrange the vertices to describe triangles
+- std::vector triangleVertices;
+- triangleVertices.reserve(vertices.size() * 6 / 4);
+- for (size_t i = 0; i < vertices.size(); i += 4)
+- {
+- triangleVertices.push_back(vertices[i]);
+- triangleVertices.push_back(vertices[i+1]);
+- triangleVertices.push_back(vertices[i+2]);
+- triangleVertices.push_back(vertices[i+1]);
+- triangleVertices.push_back(vertices[i+3]);
+- triangleVertices.push_back(vertices[i+2]);
+- }
+-
+ // Generate a unique buffer object name and put it in bufferHandle
+ GLuint bufferHandle;
+ glGenBuffers(1, &bufferHandle);
+@@ -274,7 +273,7 @@ CVertexBuffer CGUIFontTTFGL::CreateVertexBuffer(const std::vector &vert
+ // Create a data store for the buffer object bound to the GL_ARRAY_BUFFER
+ // binding point (i.e. our buffer object) and initialise it from the
+ // specified client-side pointer
+- glBufferData(GL_ARRAY_BUFFER, triangleVertices.size() * sizeof (SVertex), &triangleVertices[0], GL_STATIC_DRAW);
++ glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof (SVertex), &vertices[0], GL_STATIC_DRAW);
+ // Unbind GL_ARRAY_BUFFER
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+@@ -393,4 +392,33 @@ void CGUIFontTTFGL::DeleteHardwareTexture()
+ }
+ }
+
++#if HAS_GLES
++void CGUIFontTTFGL::CreateStaticVertexBuffers(void)
++{
++ // Bind a new buffer to the OpenGL context's GL_ELEMENT_ARRAY_BUFFER binding point
++ glGenBuffers(1, &m_elementArrayHandle);
++ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementArrayHandle);
++ // Create an array holding the mesh indices to convert quads to triangles
++ GLushort index[ELEMENT_ARRAY_MAX_CHAR_INDEX][6];
++ for (size_t i = 0; i < ELEMENT_ARRAY_MAX_CHAR_INDEX; i++)
++ {
++ index[i][0] = 4*i;
++ index[i][1] = 4*i+1;
++ index[i][2] = 4*i+2;
++ index[i][3] = 4*i+1;
++ index[i][4] = 4*i+3;
++ index[i][5] = 4*i+2;
++ }
++ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof index, index, GL_STATIC_DRAW);
++ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
++}
++
++void CGUIFontTTFGL::DestroyStaticVertexBuffers(void)
++{
++ glDeleteBuffers(1, &m_elementArrayHandle);
++}
++
++GLuint CGUIFontTTFGL::m_elementArrayHandle;
++#endif
++
+ #endif
+diff --git a/xbmc/guilib/GUIFontTTFGL.h b/xbmc/guilib/GUIFontTTFGL.h
+index 6102c90..dcf9ca1 100644
+--- a/xbmc/guilib/GUIFontTTFGL.h
++++ b/xbmc/guilib/GUIFontTTFGL.h
+@@ -30,6 +30,7 @@
+
+ #include "GUIFontTTF.h"
+ #include "system.h"
++#include "system_gl.h"
+
+
+ /*!
+@@ -47,13 +48,21 @@ class CGUIFontTTFGL : public CGUIFontTTFBase
+ #if HAS_GLES
+ virtual CVertexBuffer CreateVertexBuffer(const std::vector &vertices) const;
+ virtual void DestroyVertexBuffer(CVertexBuffer &bufferHandle) const;
++ static void CreateStaticVertexBuffers(void);
++ static void DestroyStaticVertexBuffers(void);
+ #endif
+
+ protected:
+ virtual CBaseTexture* ReallocTexture(unsigned int& newHeight);
+ virtual bool CopyCharToTexture(FT_BitmapGlyph bitGlyph, unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2);
+ virtual void DeleteHardwareTexture();
+-
++
++#if HAS_GLES
++#define ELEMENT_ARRAY_MAX_CHAR_INDEX (1000)
++
++ static GLuint m_elementArrayHandle;
++#endif
++
+ private:
+ unsigned int m_updateY1;
+ unsigned int m_updateY2;
+diff --git a/xbmc/windowing/egl/WinSystemEGL.cpp b/xbmc/windowing/egl/WinSystemEGL.cpp
+index 2bdd4fa..68f0117 100644
+--- a/xbmc/windowing/egl/WinSystemEGL.cpp
++++ b/xbmc/windowing/egl/WinSystemEGL.cpp
+@@ -29,6 +29,7 @@
+ #include "settings/AdvancedSettings.h"
+ #include "settings/Settings.h"
+ #include "settings/DisplaySettings.h"
++#include "guilib/GUIFontTTFGL.h"
+ #include "guilib/DispResource.h"
+ #include "threads/SingleLock.h"
+ #include "utils/log.h"
+@@ -207,6 +208,9 @@ bool CWinSystemEGL::CreateWindow(RESOLUTION_INFO &res)
+ return false;
+ }
+
++#if HAS_GLES
++ bool newContext = false;
++#endif
+ if (m_context == EGL_NO_CONTEXT)
+ {
+ if (!m_egl->CreateContext(m_display, m_config, contextAttrs, &m_context))
+@@ -214,6 +218,9 @@ bool CWinSystemEGL::CreateWindow(RESOLUTION_INFO &res)
+ CLog::Log(LOGERROR, "%s: Could not create context",__FUNCTION__);
+ return false;
+ }
++#if HAS_GLES
++ newContext = true;
++#endif
+ }
+
+ if (!m_egl->BindContext(m_display, m_surface, m_context))
+@@ -222,6 +229,11 @@ bool CWinSystemEGL::CreateWindow(RESOLUTION_INFO &res)
+ return false;
+ }
+
++#if HAS_GLES
++ if (newContext)
++ CGUIFontTTFGL::CreateStaticVertexBuffers();
++#endif
++
+ // for the non-trivial dirty region modes, we need the EGL buffer to be preserved across updates
+ if (g_advancedSettings.m_guiAlgorithmDirtyRegions == DIRTYREGION_SOLVER_COST_REDUCTION ||
+ g_advancedSettings.m_guiAlgorithmDirtyRegions == DIRTYREGION_SOLVER_UNION)
+@@ -243,7 +255,12 @@ bool CWinSystemEGL::DestroyWindowSystem()
+ DestroyWindow();
+
+ if (m_context != EGL_NO_CONTEXT)
++ {
++#if HAS_GLES
++ CGUIFontTTFGL::DestroyStaticVertexBuffers();
++#endif
+ m_egl->DestroyContext(m_display, m_context);
++ }
+ m_context = EGL_NO_CONTEXT;
+
+ if (m_display != EGL_NO_DISPLAY)
+
+From c0512739051fefdf815b4100213f4a43c22bc16c Mon Sep 17 00:00:00 2001
+From: Ben Avison
+Date: Thu, 1 May 2014 16:28:39 +0100
+Subject: [PATCH 18/61] Improved file buffering in CArchive
+
+Even though memcpy is typically inlined by the compiler into byte/word loads
+and stores (at least for release builds), the frequency with which 1, 2 and 4
+byte loads/stores are encountered in cases where the size is *not*
+determinable at compile time is still high enough that it's worth handling
+these specially. On the ARM1176JZF-S in the Raspberry Pi, this improves the
+total time to open a library (in the case where it's fetched from a CArchive)
+by around 4%.
+
+It should be noted that this code uses 16-bit and 32-bit word loads and
+stores that are not necessarily aligned to their respective widths. It is
+possible that there are some architectures out there which do not support
+this, although all ARMs since ARMv6 have supported it (and ARMs earlier than
+that are probably not powerful enough to be good targets for XBMC).
+---
+ xbmc/utils/Archive.h | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/xbmc/utils/Archive.h b/xbmc/utils/Archive.h
+index 6ed0f8f..8506d95 100644
+--- a/xbmc/utils/Archive.h
++++ b/xbmc/utils/Archive.h
+@@ -154,9 +154,17 @@ class CArchive
+ * than waiting until we attempt to put more data into an already full buffer */
+ if (m_BufferRemain > size)
+ {
++ switch (size)
++ {
++ case 1: *m_BufferPos++ = *ptr; m_BufferRemain--; break;
++ case 2: *(uint16_t *) m_BufferPos = *(const uint16_t *) ptr; m_BufferPos += 2; m_BufferRemain -= 2; break;
++ case 4: *(uint32_t *) m_BufferPos = *(const uint32_t *) ptr; m_BufferPos += 4; m_BufferRemain -= 4; break;
++ default:
+ memcpy(m_BufferPos, ptr, size);
+ m_BufferPos += size;
+ m_BufferRemain -= size;
++ break;
++ }
+ return *this;
+ }
+ else
+@@ -171,9 +179,17 @@ class CArchive
+ /* Note, refilling the buffer is deferred until we know we need to read more from it */
+ if (m_BufferRemain >= size)
+ {
++ switch (size)
++ {
++ case 1: *ptr = *m_BufferPos++; m_BufferRemain--; break;
++ case 2: *(uint16_t *) ptr = *(const uint16_t *) m_BufferPos; m_BufferPos += 2; m_BufferRemain -= 2; break;
++ case 4: *(uint32_t *) ptr = *(const uint32_t *) m_BufferPos; m_BufferPos += 4; m_BufferRemain -= 4; break;
++ default:
+ memcpy(ptr, m_BufferPos, size);
+ m_BufferPos += size;
+ m_BufferRemain -= size;
++ break;
++ }
+ return *this;
+ }
+ else
+
+From 51b24a82bc14025ce06c0edf513725037ad12fae Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Wed, 10 Sep 2014 22:07:21 +0100
+Subject: [PATCH 19/61] [mmal] Allow mmal codec for dvd stills
+
+---
+ xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp
+index 10648c5..bea5e4f 100644
+--- a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp
++++ b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp
+@@ -194,6 +194,10 @@ CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, unsigne
+ #endif
+ CLog::Log(LOGDEBUG, "CDVDFactoryCodec: compiled in hardware support: %s", hwSupport.c_str());
+
++#if defined(HAS_MMAL)
++ // mmal can handle dvd playback including stills
++ if (!CSettings::Get().GetBool("videoplayer.usemmal"))
++#endif
+ if (hint.stills && (hint.codec == AV_CODEC_ID_MPEG2VIDEO || hint.codec == AV_CODEC_ID_MPEG1VIDEO))
+ {
+ // If dvd is an mpeg2 and hint.stills
+
+From 0537e3a504c1f23c5db538a5b74b8993cc4919a4 Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Tue, 12 Aug 2014 00:31:36 +0100
+Subject: [PATCH 20/61] [omxcodec] Don't force software codec with dvds
+
+---
+ xbmc/cores/dvdplayer/DVDPlayer.cpp | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp
+index aae59dc..12a3ed6 100644
+--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp
++++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp
+@@ -3225,7 +3225,9 @@ bool CDVDPlayer::OpenVideoStream(CDVDStreamInfo& hint, bool reset)
+ hint.aspect = aspect;
+ hint.forced_aspect = true;
+ }
++#ifndef TARGET_RASPBERRY_PI
+ hint.software = true;
++#endif
+ }
+
+ CDVDInputStream::IMenus* pMenus = dynamic_cast(m_pInputStream);
+
+From 48065b31bcc20416925a437417ff30c309ca422d Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Wed, 16 Apr 2014 21:18:06 +0100
+Subject: [PATCH 21/61] [omxplayer] Don't propagate 3d flags based on supported
+ 3d modes
+
+---
+ xbmc/cores/omxplayer/OMXPlayerVideo.cpp | 29 ++++-------------------------
+ 1 file changed, 4 insertions(+), 25 deletions(-)
+
+diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
+index ac838ce..605318c9 100644
+--- a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
++++ b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
+@@ -759,36 +759,15 @@ void OMXPlayerVideo::ResolutionUpdateCallBack(uint32_t width, uint32_t height, f
+ unsigned flags = 0;
+ ERenderFormat format = RENDER_FMT_BYPASS;
+
++ /* figure out steremode expected based on user settings and hints */
++ unsigned int stereo_flags = GetStereoModeFlags(GetStereoMode());
++
+ if(m_bAllowFullscreen)
+ {
+ flags |= CONF_FLAGS_FULLSCREEN;
+ m_bAllowFullscreen = false; // only allow on first configure
+ }
+-
+- flags |= GetStereoModeFlags(GetStereoMode());
+-
+- if(flags & CONF_FLAGS_STEREO_MODE_SBS)
+- {
+- if(g_Windowing.Support3D(video_width, video_height, D3DPRESENTFLAG_MODE3DSBS))
+- CLog::Log(LOGNOTICE, "3DSBS movie found");
+- else
+- {
+- flags &= ~CONF_FLAGS_STEREO_MODE_MASK(~0);
+- CLog::Log(LOGNOTICE, "3DSBS movie found but not supported");
+- }
+- }
+- else if(flags & CONF_FLAGS_STEREO_MODE_TAB)
+- {
+- if(g_Windowing.Support3D(video_width, video_height, D3DPRESENTFLAG_MODE3DTB))
+- CLog::Log(LOGNOTICE, "3DTB movie found");
+- else
+- {
+- flags &= ~CONF_FLAGS_STEREO_MODE_MASK(~0);
+- CLog::Log(LOGNOTICE, "3DTB movie found but not supported");
+- }
+- }
+- else
+- CLog::Log(LOGNOTICE, "not a 3D movie");
++ flags |= stereo_flags;
+
+ unsigned int iDisplayWidth = width;
+ unsigned int iDisplayHeight = height;
+
+From 8da39d7dc81be90459a1ffa8c67fb1dd826d1e54 Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Thu, 17 Apr 2014 13:00:52 +0100
+Subject: [PATCH 22/61] [graphics] Don't set stereo mode based on resolution
+
+The resolution change should follow stereo mode
+---
+ xbmc/guilib/GraphicContext.cpp | 35 +++++++++++++++++++----------------
+ 1 file changed, 19 insertions(+), 16 deletions(-)
+
+diff --git a/xbmc/guilib/GraphicContext.cpp b/xbmc/guilib/GraphicContext.cpp
+index 3cb5587..fe6ebf4 100644
+--- a/xbmc/guilib/GraphicContext.cpp
++++ b/xbmc/guilib/GraphicContext.cpp
+@@ -436,26 +436,29 @@ void CGraphicContext::SetVideoResolutionInternal(RESOLUTION res, bool forceUpdat
+ RESOLUTION_INFO info_org = CDisplaySettings::Get().GetResolutionInfo(res);
+ RESOLUTION_INFO info_last = CDisplaySettings::Get().GetResolutionInfo(lastRes);
+
+- RENDER_STEREO_MODE stereo_mode = m_stereoMode;
+-
+ // if the new mode is an actual stereo mode, switch to that
+ // if the old mode was an actual stereo mode, switch to no 3d mode
+- if (info_org.dwFlags & D3DPRESENTFLAG_MODE3DTB)
+- stereo_mode = RENDER_STEREO_MODE_SPLIT_HORIZONTAL;
+- else if (info_org.dwFlags & D3DPRESENTFLAG_MODE3DSBS)
+- stereo_mode = RENDER_STEREO_MODE_SPLIT_VERTICAL;
+- else if ((info_last.dwFlags & D3DPRESENTFLAG_MODE3DSBS) != 0
+- || (info_last.dwFlags & D3DPRESENTFLAG_MODE3DTB) != 0)
+- stereo_mode = RENDER_STEREO_MODE_OFF;
+-
+- if(stereo_mode != m_stereoMode)
++ // only do this if 3D flags have changed
++ if ((info_org.dwFlags ^ info_last.dwFlags) & (D3DPRESENTFLAG_MODE3DTB | D3DPRESENTFLAG_MODE3DSBS))
+ {
+- m_stereoView = RENDER_STEREO_VIEW_OFF;
+- m_stereoMode = stereo_mode;
+- m_nextStereoMode = stereo_mode;
+- CSettings::Get().SetInt("videoscreen.stereoscopicmode", (int)m_stereoMode);
+- }
++ RENDER_STEREO_MODE stereo_mode = m_stereoMode;
++
++ if (info_org.dwFlags & D3DPRESENTFLAG_MODE3DTB)
++ stereo_mode = RENDER_STEREO_MODE_SPLIT_HORIZONTAL;
++ else if (info_org.dwFlags & D3DPRESENTFLAG_MODE3DSBS)
++ stereo_mode = RENDER_STEREO_MODE_SPLIT_VERTICAL;
++ else if ((info_last.dwFlags & D3DPRESENTFLAG_MODE3DSBS) != 0
++ || (info_last.dwFlags & D3DPRESENTFLAG_MODE3DTB) != 0)
++ stereo_mode = RENDER_STEREO_MODE_OFF;
+
++ if(stereo_mode != m_stereoMode)
++ {
++ m_stereoView = RENDER_STEREO_VIEW_OFF;
++ m_stereoMode = stereo_mode;
++ m_nextStereoMode = stereo_mode;
++ CSettings::Get().SetInt("videoscreen.stereoscopicmode", (int)m_stereoMode);
++ }
++ }
+ RESOLUTION_INFO info_mod = GetResInfo(res);
+
+ m_iScreenWidth = info_mod.iWidth;
+
+From a2fa758a0975c317360bed25e72f359f24545e50 Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Thu, 17 Apr 2014 13:01:51 +0100
+Subject: [PATCH 23/61] [graphics] Allow switching to a more suitable 3D
+ resolution
+
+---
+ xbmc/guilib/GraphicContext.cpp | 40 +++++++++++++++++++++++++++++++++++++++-
+ xbmc/guilib/GraphicContext.h | 1 +
+ 2 files changed, 40 insertions(+), 1 deletion(-)
+
+diff --git a/xbmc/guilib/GraphicContext.cpp b/xbmc/guilib/GraphicContext.cpp
+index fe6ebf4..04d0756 100644
+--- a/xbmc/guilib/GraphicContext.cpp
++++ b/xbmc/guilib/GraphicContext.cpp
+@@ -35,6 +35,7 @@
+ #include "utils/JobManager.h"
+ #include "video/VideoReferenceClock.h"
+ #include "cores/IPlayer.h"
++#include
+
+ using namespace std;
+
+@@ -500,6 +501,43 @@ RESOLUTION CGraphicContext::GetVideoResolution() const
+ return m_Resolution;
+ }
+
++RESOLUTION CGraphicContext::Get3DVideoResolution(RESOLUTION resolution, RENDER_STEREO_MODE mode) const
++{
++ RESOLUTION best = resolution;
++ RESOLUTION_INFO curr = CDisplaySettings::Get().GetResolutionInfo(best);
++ // Find closest refresh rate
++ for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); i++)
++ {
++ const RESOLUTION_INFO info = CDisplaySettings::Get().GetResolutionInfo((RESOLUTION)i);
++
++ //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
++ || (info.dwFlags & D3DPRESENTFLAG_INTERLACED) != (curr.dwFlags & D3DPRESENTFLAG_INTERLACED)
++ || fabs(info.fRefreshRate - curr.fRefreshRate) >= FLT_EPSILON)
++ continue;
++
++ if (mode == RENDER_STEREO_MODE_SPLIT_VERTICAL && info.dwFlags & D3DPRESENTFLAG_MODE3DSBS)
++ {
++ best = (RESOLUTION)i;
++ break;
++ }
++ else if (mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL && info.dwFlags & D3DPRESENTFLAG_MODE3DTB)
++ {
++ best = (RESOLUTION)i;
++ break;
++ }
++ else if ((mode == RENDER_STEREO_MODE_OFF || mode == RENDER_STEREO_MODE_MONO) && !(info.dwFlags & (D3DPRESENTFLAG_MODE3DSBS|D3DPRESENTFLAG_MODE3DTB)))
++ {
++ best = (RESOLUTION)i;
++ break;
++ }
++ }
++ return best;
++}
++
+ void CGraphicContext::ResetOverscan(RESOLUTION_INFO &res)
+ {
+ res.Overscan.left = 0;
+@@ -1037,7 +1075,7 @@ void CGraphicContext::Flip(const CDirtyRegionList& dirty)
+ if(m_stereoMode != m_nextStereoMode)
+ {
+ m_stereoMode = m_nextStereoMode;
+- SetVideoResolution(GetVideoResolution(), true);
++ SetVideoResolution(Get3DVideoResolution(m_Resolution, m_stereoMode), true);
+ g_windowManager.SendMessage(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_RENDERER_RESET);
+ }
+ }
+diff --git a/xbmc/guilib/GraphicContext.h b/xbmc/guilib/GraphicContext.h
+index 2904c1b..8d3774f 100644
+--- a/xbmc/guilib/GraphicContext.h
++++ b/xbmc/guilib/GraphicContext.h
+@@ -108,6 +108,7 @@ class CGraphicContext : public CCriticalSection,
+ bool IsValidResolution(RESOLUTION res);
+ void SetVideoResolution(RESOLUTION res, bool forceUpdate = false);
+ RESOLUTION GetVideoResolution() const;
++ RESOLUTION Get3DVideoResolution(RESOLUTION resolution, RENDER_STEREO_MODE mode) const;
+ void ResetOverscan(RESOLUTION res, OVERSCAN &overscan);
+ void ResetOverscan(RESOLUTION_INFO &resinfo);
+ void ResetScreenParameters(RESOLUTION res);
+
+From 0ac98adc456416d3f687a81924659397d4a9ef7b Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Thu, 17 Apr 2014 13:38:55 +0100
+Subject: [PATCH 24/61] [3D] Support switching to 3D resolutions
+
+Include matching 3D flags (SBS/TAB) in the score of a resolution to switch to, to enable switching to 3d modes.
+Also remove the old code that treated 3D modes differently when assigning a score.
+---
+ xbmc/cores/VideoRenderers/BaseRenderer.cpp | 47 +++++++++++-------------------
+ 1 file changed, 17 insertions(+), 30 deletions(-)
+
+diff --git a/xbmc/cores/VideoRenderers/BaseRenderer.cpp b/xbmc/cores/VideoRenderers/BaseRenderer.cpp
+index 83c3adb..8076e76 100644
+--- a/xbmc/cores/VideoRenderers/BaseRenderer.cpp
++++ b/xbmc/cores/VideoRenderers/BaseRenderer.cpp
+@@ -222,10 +222,14 @@ void CBaseRenderer::FindResolutionFromFpsMatch(float fps, float& weight)
+ RESOLUTION CBaseRenderer::FindClosestResolution(float fps, float multiplier, RESOLUTION current, float& weight)
+ {
+ RESOLUTION_INFO curr = g_graphicsContext.GetResInfo(current);
++ RENDER_STEREO_MODE stereo_mode = g_graphicsContext.GetStereoMode();
+
+ float fRefreshRate = fps;
+
+- float last_diff = fRefreshRate;
++ int c_weight = MathUtils::round_int(RefreshWeight(curr.fRefreshRate, fRefreshRate * multiplier) * 1000.0);
++ if (!(stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL) != !(curr.dwFlags & D3DPRESENTFLAG_MODE3DSBS) ||
++ !(stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) != !(curr.dwFlags & D3DPRESENTFLAG_MODE3DTB))
++ c_weight += 1000;
+
+ // Find closest refresh rate
+ for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); i++)
+@@ -241,40 +245,23 @@ RESOLUTION CBaseRenderer::FindClosestResolution(float fps, float multiplier, RES
+ || info.fRefreshRate < (fRefreshRate * multiplier / 1.001) - 0.001)
+ continue;
+
+- // For 3D choose the closest refresh rate
+- if(CONF_FLAGS_STEREO_MODE_MASK(m_iFlags))
+- {
+- float diff = (info.fRefreshRate - fRefreshRate);
+- if(diff < 0)
+- diff *= -1.0f;
++ int i_weight = MathUtils::round_int(RefreshWeight(info.fRefreshRate, fRefreshRate * multiplier) * 1000.0);
+
+- if(diff < last_diff)
+- {
+- last_diff = diff;
+- current = (RESOLUTION)i;
+- curr = info;
+- }
+- }
+- else
+- {
+- int c_weight = MathUtils::round_int(RefreshWeight(curr.fRefreshRate, fRefreshRate * multiplier) * 1000.0);
+- int i_weight = MathUtils::round_int(RefreshWeight(info.fRefreshRate, fRefreshRate * multiplier) * 1000.0);
++ if (!(stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL) != !(info.dwFlags & D3DPRESENTFLAG_MODE3DSBS) ||
++ !(stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) != !(info.dwFlags & D3DPRESENTFLAG_MODE3DTB))
++ i_weight += 1000;
+
+- // Closer the better, prefer higher refresh rate if the same
+- if ((i_weight < c_weight)
+- || (i_weight == c_weight && info.fRefreshRate > curr.fRefreshRate))
+- {
+- current = (RESOLUTION)i;
+- curr = info;
+- }
++ // Closer the better, prefer higher refresh rate if the same
++ if ((i_weight < c_weight)
++ || (i_weight == c_weight && info.fRefreshRate > curr.fRefreshRate))
++ {
++ current = (RESOLUTION)i;
++ curr = info;
++ c_weight = i_weight;
+ }
+ }
+
+- // For 3D overwrite weight
+- if(CONF_FLAGS_STEREO_MODE_MASK(m_iFlags))
+- weight = 0;
+- else
+- weight = RefreshWeight(curr.fRefreshRate, fRefreshRate * multiplier);
++ weight = RefreshWeight(curr.fRefreshRate, fRefreshRate * multiplier);
+
+ return current;
+ }
+
+From 7fef1d13ee7d83bcbe3ea5b8f74461c5744b9ca9 Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Wed, 23 Apr 2014 00:05:07 +0100
+Subject: [PATCH 25/61] [graphics] Make pixel ratio for 3d modes consistent
+
+Note: Use the stored stereo flags from lists of resolutions.
+Use current stereo mode for current resolution.
+---
+ xbmc/cores/VideoRenderers/BaseRenderer.cpp | 10 +++----
+ xbmc/guilib/GraphicContext.cpp | 37 ++++++++++++-------------
+ xbmc/guilib/GraphicContext.h | 12 ++++++--
+ xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp | 8 ------
+ 4 files changed, 32 insertions(+), 35 deletions(-)
+
+diff --git a/xbmc/cores/VideoRenderers/BaseRenderer.cpp b/xbmc/cores/VideoRenderers/BaseRenderer.cpp
+index 8076e76..9118cb0 100644
+--- a/xbmc/cores/VideoRenderers/BaseRenderer.cpp
++++ b/xbmc/cores/VideoRenderers/BaseRenderer.cpp
+@@ -119,7 +119,7 @@ bool CBaseRenderer::FindResolutionFromOverride(float fps, float& weight, bool fa
+
+ for (size_t j = (int)RES_DESKTOP; j < CDisplaySettings::Get().ResolutionInfoSize(); j++)
+ {
+- RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)j);
++ RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)j, g_graphicsContext.GetStereoMode((RESOLUTION)j));
+
+ if (info.iScreenWidth == curr.iScreenWidth
+ && info.iScreenHeight == curr.iScreenHeight
+@@ -179,7 +179,7 @@ void CBaseRenderer::FindResolutionFromFpsMatch(float fps, float& weight)
+ //get the resolution with the refreshrate closest to 60 hertz
+ for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); i++)
+ {
+- RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i);
++ RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i, g_graphicsContext.GetStereoMode((RESOLUTION)i));
+
+ if (MathUtils::round_int(info.fRefreshRate) == 60
+ && info.iScreenWidth == curr.iScreenWidth
+@@ -200,7 +200,7 @@ void CBaseRenderer::FindResolutionFromFpsMatch(float fps, float& weight)
+ CLog::Log(LOGDEBUG, "60 hertz refreshrate not available, choosing highest");
+ for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); i++)
+ {
+- RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i);
++ RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i, g_graphicsContext.GetStereoMode((RESOLUTION)i));
+
+ if (info.fRefreshRate > curr.fRefreshRate
+ && info.iScreenWidth == curr.iScreenWidth
+@@ -234,14 +234,14 @@ RESOLUTION CBaseRenderer::FindClosestResolution(float fps, float multiplier, RES
+ // Find closest refresh rate
+ for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); i++)
+ {
+- const RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i);
++ const RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i, g_graphicsContext.GetStereoMode((RESOLUTION)i));
+
+ //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
+- || (info.dwFlags & D3DPRESENTFLAG_MODEMASK) != (curr.dwFlags & D3DPRESENTFLAG_MODEMASK)
++ || (info.dwFlags & D3DPRESENTFLAG_INTERLACED) != (curr.dwFlags & D3DPRESENTFLAG_INTERLACED)
+ || info.fRefreshRate < (fRefreshRate * multiplier / 1.001) - 0.001)
+ continue;
+
+diff --git a/xbmc/guilib/GraphicContext.cpp b/xbmc/guilib/GraphicContext.cpp
+index 04d0756..93bd207 100644
+--- a/xbmc/guilib/GraphicContext.cpp
++++ b/xbmc/guilib/GraphicContext.cpp
+@@ -747,32 +747,33 @@ void CGraphicContext::ApplyStateBlock()
+ g_Windowing.ApplyStateBlock();
+ }
+
+-const RESOLUTION_INFO CGraphicContext::GetResInfo(RESOLUTION res) const
++RENDER_STEREO_MODE CGraphicContext::GetStereoMode(RESOLUTION res) const
+ {
+ RESOLUTION_INFO info = CDisplaySettings::Get().GetResolutionInfo(res);
++ return (info.dwFlags & D3DPRESENTFLAG_MODE3DTB) ? RENDER_STEREO_MODE_SPLIT_HORIZONTAL :
++ (info.dwFlags & D3DPRESENTFLAG_MODE3DSBS) ? RENDER_STEREO_MODE_SPLIT_VERTICAL : RENDER_STEREO_MODE_OFF;
++}
+
+- if(m_stereoMode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL)
++const RESOLUTION_INFO CGraphicContext::GetResInfo(RESOLUTION res, RENDER_STEREO_MODE stereoMode) const
++{
++ RESOLUTION_INFO info = CDisplaySettings::Get().GetResolutionInfo(res);
++
++ if(stereoMode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL)
+ {
+- if((info.dwFlags & D3DPRESENTFLAG_MODE3DTB) == 0)
+- {
+- info.fPixelRatio /= 2;
+- info.iBlanking = 0;
+- info.dwFlags |= D3DPRESENTFLAG_MODE3DTB;
+- }
++ info.fPixelRatio /= 2;
++ info.iBlanking = 0;
++ info.dwFlags |= D3DPRESENTFLAG_MODE3DTB;
+ info.iHeight = (info.iHeight - info.iBlanking) / 2;
+ info.Overscan.top /= 2;
+ info.Overscan.bottom = (info.Overscan.bottom - info.iBlanking) / 2;
+ info.iSubtitles = (info.iSubtitles - info.iBlanking) / 2;
+ }
+
+- if(m_stereoMode == RENDER_STEREO_MODE_SPLIT_VERTICAL)
++ if(stereoMode == RENDER_STEREO_MODE_SPLIT_VERTICAL)
+ {
+- if((info.dwFlags & D3DPRESENTFLAG_MODE3DSBS) == 0)
+- {
+- info.fPixelRatio *= 2;
+- info.iBlanking = 0;
+- info.dwFlags |= D3DPRESENTFLAG_MODE3DSBS;
+- }
++ info.fPixelRatio *= 2;
++ info.iBlanking = 0;
++ info.dwFlags |= D3DPRESENTFLAG_MODE3DSBS;
+ info.iWidth = (info.iWidth - info.iBlanking) / 2;
+ info.Overscan.left /= 2;
+ info.Overscan.right = (info.Overscan.right - info.iBlanking) / 2;
+@@ -790,16 +791,14 @@ void CGraphicContext::SetResInfo(RESOLUTION res, const RESOLUTION_INFO& info)
+ if(info.dwFlags & D3DPRESENTFLAG_MODE3DSBS)
+ {
+ curr.Overscan.right = info.Overscan.right * 2 + info.iBlanking;
+- if((curr.dwFlags & D3DPRESENTFLAG_MODE3DSBS) == 0)
+- curr.fPixelRatio /= 2.0;
++ curr.fPixelRatio /= 2.0;
+ }
+
+ if(info.dwFlags & D3DPRESENTFLAG_MODE3DTB)
+ {
+ curr.Overscan.bottom = info.Overscan.bottom * 2 + info.iBlanking;
+ curr.iSubtitles = info.iSubtitles * 2 + info.iBlanking;
+- if((curr.dwFlags & D3DPRESENTFLAG_MODE3DTB) == 0)
+- curr.fPixelRatio *= 2.0;
++ curr.fPixelRatio *= 2.0;
+ }
+ }
+
+diff --git a/xbmc/guilib/GraphicContext.h b/xbmc/guilib/GraphicContext.h
+index 8d3774f..f2e122d 100644
+--- a/xbmc/guilib/GraphicContext.h
++++ b/xbmc/guilib/GraphicContext.h
+@@ -120,11 +120,15 @@ class CGraphicContext : public CCriticalSection,
+ void GetAllowedResolutions(std::vector &res);
+
+ // output scaling
++ const RESOLUTION_INFO GetResInfo(RESOLUTION res) const
++ {
++ return GetResInfo(res, GetStereoMode());
++ }
+ const RESOLUTION_INFO GetResInfo() const
+ {
+ return GetResInfo(m_Resolution);
+ }
+- const RESOLUTION_INFO GetResInfo(RESOLUTION res) const;
++ const RESOLUTION_INFO GetResInfo(RESOLUTION res, RENDER_STEREO_MODE stereo_mode) const;
+ void SetResInfo(RESOLUTION res, const RESOLUTION_INFO& info);
+
+ /* \brief Get UI scaling information from a given resolution to the screen resolution.
+@@ -161,9 +165,11 @@ class CGraphicContext : public CCriticalSection,
+ void RestoreOrigin();
+ void SetCameraPosition(const CPoint &camera);
+ void SetStereoView(RENDER_STEREO_VIEW view);
+- RENDER_STEREO_VIEW GetStereoView() { return m_stereoView; }
++ RENDER_STEREO_VIEW GetStereoView() const { return m_stereoView; }
+ void SetStereoMode(RENDER_STEREO_MODE mode) { m_nextStereoMode = mode; }
+- RENDER_STEREO_MODE GetStereoMode() { return m_stereoMode; }
++ RENDER_STEREO_MODE GetStereoMode() const { return m_stereoMode; }
++ RENDER_STEREO_MODE GetStereoMode(RESOLUTION res) const;
++
+ void RestoreCameraPosition();
+ /*! \brief Set a region in which to clip all rendering
+ Anything that is rendered after setting a clip region will be clipped so that no part renders
+diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp
+index c58c28a..bf1e589 100644
+--- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp
++++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp
+@@ -449,15 +449,9 @@ bool CEGLNativeTypeRaspberryPI::ProbeResolutions(std::vector &r
+ m_desktopRes.fPixelRatio = get_display_aspect_ratio((HDMI_ASPECT_T)tv_state.display.hdmi.display_options.aspect) / ((float)m_desktopRes.iScreenWidth / (float)m_desktopRes.iScreenHeight);
+ // Also add 3D flags
+ if (tv_state.display.hdmi.format_3d == HDMI_3D_FORMAT_SBS_HALF)
+- {
+ m_desktopRes.dwFlags |= D3DPRESENTFLAG_MODE3DSBS;
+- m_desktopRes.fPixelRatio *= 2.0;
+- }
+ else if (tv_state.display.hdmi.format_3d == HDMI_3D_FORMAT_TB_HALF)
+- {
+ m_desktopRes.dwFlags |= D3DPRESENTFLAG_MODE3DTB;
+- m_desktopRes.fPixelRatio *= 0.5;
+- }
+ HDMI_PROPERTY_PARAM_T property;
+ property.property = HDMI_PROPERTY_PIXEL_CLOCK_TYPE;
+ vc_tv_hdmi_get_property(&property);
+@@ -600,7 +594,6 @@ void CEGLNativeTypeRaspberryPI::GetSupportedModes(HDMI_RES_GROUP_T group, std::v
+ RESOLUTION_INFO res2 = res;
+ res2.dwFlags |= D3DPRESENTFLAG_MODE3DSBS;
+ res2.fPixelRatio = get_display_aspect_ratio((HDMI_ASPECT_T)tv->aspect_ratio) / ((float)res2.iScreenWidth / (float)res2.iScreenHeight);
+- res2.fPixelRatio *= 2.0f;
+ res2.iSubtitles = (int)(0.965 * res2.iHeight);
+
+ AddUniqueResolution(res2, resolutions);
+@@ -616,7 +609,6 @@ void CEGLNativeTypeRaspberryPI::GetSupportedModes(HDMI_RES_GROUP_T group, std::v
+ RESOLUTION_INFO res2 = res;
+ res2.dwFlags |= D3DPRESENTFLAG_MODE3DTB;
+ res2.fPixelRatio = get_display_aspect_ratio((HDMI_ASPECT_T)tv->aspect_ratio) / ((float)res2.iScreenWidth / (float)res2.iScreenHeight);
+- res2.fPixelRatio *= 0.5f;
+ res2.iSubtitles = (int)(0.965 * res2.iHeight);
+
+ AddUniqueResolution(res2, resolutions);
+
+From 226505052e30a82e9df0517ee8a5c7e4e3ba230f Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Sun, 10 Aug 2014 16:45:16 +0100
+Subject: [PATCH 26/61] filesystem: Make support of browsing into archives
+ optional
+
+The ability to browse, scan and play content in archives can cause problems on low powered/low memory devices.
+It's quite common to see reports of a large rar file that causes xbmc to crash with an out-of-memory error when browsing or scanning.
+It also can be slow as any archive in the directory is opened and extracted.
+
+Add a settings option to enable this feature and default to disabled on Pi
+---
+ language/English/strings.po | 9 +++++++++
+ system/settings/rbp.xml | 10 ++++++++++
+ system/settings/settings.xml | 5 +++++
+ xbmc/filesystem/FileDirectoryFactory.cpp | 4 ++++
+ 4 files changed, 28 insertions(+)
+
+diff --git a/language/English/strings.po b/language/English/strings.po
+index 15090fc..8e67be0 100755
+--- a/language/English/strings.po
++++ b/language/English/strings.po
+@@ -16115,4 +16115,13 @@ msgstr ""
+ #: system/settings/rbp.xml
+ msgctxt "#38010"
+ msgid "GPU accelerated"
++
++#: system/settings/settings.xml
++msgctxt "#38020"
++msgid "Support browsing into archives"
++msgstr ""
++
++#: system/settings/settings.xml
++msgctxt "#38021"
++msgid "Allow viewing and playing files in archives (e.g. zip, rar)"
+ msgstr ""
+diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml
+index f572eed..f3c8a01 100644
+--- a/system/settings/rbp.xml
++++ b/system/settings/rbp.xml
+@@ -1,5 +1,15 @@
+
+
++
++
++
++
++ false
++
++
++
++
++
+
+
+
+diff --git a/system/settings/settings.xml b/system/settings/settings.xml
+index 367542d..0db66a2 100644
+--- a/system/settings/settings.xml
++++ b/system/settings/settings.xml
+@@ -226,6 +226,11 @@
+ false
+
+
++
++ 1
++ true
++
++
+
+
+
+diff --git a/xbmc/filesystem/FileDirectoryFactory.cpp b/xbmc/filesystem/FileDirectoryFactory.cpp
+index 2fd8777..3b294cd 100644
+--- a/xbmc/filesystem/FileDirectoryFactory.cpp
++++ b/xbmc/filesystem/FileDirectoryFactory.cpp
+@@ -46,6 +46,7 @@
+ #include "Directory.h"
+ #include "File.h"
+ #include "ZipManager.h"
++#include "settings/Settings.h"
+ #include "settings/AdvancedSettings.h"
+ #include "FileItem.h"
+ #include "utils/StringUtils.h"
+@@ -142,6 +143,8 @@ IFileDirectory* CFileDirectoryFactory::Create(const CURL& url, CFileItem* pItem,
+ return NULL;
+ }
+ #endif
++ if (CSettings::Get().GetBool("filelists.browsearchives"))
++ {
+ if (url.IsFileType("zip"))
+ {
+ CURL zipURL = URIUtils::CreateArchivePath("zip", url);
+@@ -215,6 +218,7 @@ IFileDirectory* CFileDirectoryFactory::Create(const CURL& url, CFileItem* pItem,
+ }
+ return NULL;
+ }
++ }
+ if (url.IsFileType("xsp"))
+ { // XBMC Smart playlist - just XML renamed to XSP
+ // read the name of the playlist in
+
+From f4bb933ecf5264da34f4016254a87318160ed59e Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Mon, 27 Oct 2014 13:06:57 +0000
+Subject: [PATCH 28/61] [rbp] Make cachemembuffersize default depend on memory
+ size
+
+---
+ xbmc/linux/RBP.cpp | 5 +++++
+ xbmc/settings/AdvancedSettings.cpp | 5 +++++
+ 2 files changed, 10 insertions(+)
+
+diff --git a/xbmc/linux/RBP.cpp b/xbmc/linux/RBP.cpp
+index ba1a3d0..5119949 100644
+--- a/xbmc/linux/RBP.cpp
++++ b/xbmc/linux/RBP.cpp
+@@ -22,6 +22,7 @@
+ #if defined(TARGET_RASPBERRY_PI)
+
+ #include "settings/Settings.h"
++#include "settings/AdvancedSettings.h"
+ #include "utils/log.h"
+
+ #include "cores/omxplayer/OMXImage.h"
+@@ -84,6 +85,9 @@ bool CRBP::Initialize()
+ if (!m_gui_resolution_limit)
+ m_gui_resolution_limit = m_gpu_mem < 128 ? 720:1080;
+
++ if (g_advancedSettings.m_cacheMemBufferSize == ~0U)
++ g_advancedSettings.m_cacheMemBufferSize = m_arm_mem < 256 ? 1024 * 1024 * 2 : 1024 * 1024 * 20;
++
+ g_OMXImage.Initialize();
+ m_omx_image_init = true;
+ return true;
+@@ -96,6 +100,7 @@ void CRBP::LogFirmwareVerison()
+ response[sizeof(response) - 1] = '\0';
+ CLog::Log(LOGNOTICE, "Raspberry PI firmware version: %s", response);
+ CLog::Log(LOGNOTICE, "ARM mem: %dMB GPU mem: %dMB MPG2:%d WVC1:%d", m_arm_mem, m_gpu_mem, m_codec_mpg2_enabled, m_codec_wvc1_enabled);
++ CLog::Log(LOGNOTICE, "cacheMemBufferSize: %dMB", g_advancedSettings.m_cacheMemBufferSize >> 20);
+ m_DllBcmHost->vc_gencmd(response, sizeof response, "get_config int");
+ response[sizeof(response) - 1] = '\0';
+ CLog::Log(LOGNOTICE, "Config:\n%s", response);
+diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp
+index 478d725..69b7832 100644
+--- a/xbmc/settings/AdvancedSettings.cpp
++++ b/xbmc/settings/AdvancedSettings.cpp
+@@ -365,7 +365,12 @@ void CAdvancedSettings::Initialize()
+ m_bPVRAutoScanIconsUserSet = false;
+ m_iPVRNumericChannelSwitchTimeout = 1000;
+
++#ifdef TARGET_RASPBERRY_PI
++ // want default to be memory dependent, but interface to gpu not available yet, so set in RBP.cpp
++ m_cacheMemBufferSize = ~0;
++#else
+ m_cacheMemBufferSize = 1024 * 1024 * 20;
++#endif
+ m_networkBufferMode = 0; // Default (buffer all internet streams/filesystems)
+ // the following setting determines the readRate of a player data
+ // as multiply of the default data read rate
+
+
+From 2d804672d3ff76acc05ce146aaf0addbd17b9a72 Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Mon, 16 Jun 2014 19:06:00 +0100
+Subject: [PATCH 30/61] [experimental] Disable quiet-noise generation
+
+---
+ xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.cpp | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.cpp
+index b391ff3..463a89c 100644
+--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.cpp
++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESink.cpp
+@@ -873,6 +873,7 @@ void CActiveAESink::SwapInit(CSampleBuffer* samples)
+
+ void CActiveAESink::GenerateNoise()
+ {
++#ifndef TARGET_RASPBERRY_PI
+ int nb_floats = m_sampleOfSilence.pkt->max_nb_samples;
+ nb_floats *= m_sampleOfSilence.pkt->config.channels;
+
+@@ -913,6 +914,7 @@ void CActiveAESink::GenerateNoise()
+
+ _aligned_free(noise);
+ delete resampler;
++#endif
+ }
+
+ void CActiveAESink::SetSilenceTimer()
+
+From 1ef873265263d237960c9052ab0fe425eaa3f08b Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Fri, 30 May 2014 14:58:43 +0100
+Subject: [PATCH 31/61] [settings] Experiment: Report DESKTOP resolution in
+ video settings
+
+---
+ xbmc/settings/DisplaySettings.cpp | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/xbmc/settings/DisplaySettings.cpp b/xbmc/settings/DisplaySettings.cpp
+index 6902f83..50c5f97 100644
+--- a/xbmc/settings/DisplaySettings.cpp
++++ b/xbmc/settings/DisplaySettings.cpp
+@@ -674,6 +674,9 @@ void CDisplaySettings::SettingOptionsResolutionsFiller(const CSetting *setting,
+ vector resolutions = g_Windowing.ScreenResolutions(info.iScreen, info.fRefreshRate);
+ for (vector::const_iterator resolution = resolutions.begin(); resolution != resolutions.end(); ++resolution)
+ {
++if (resolution->ResInfo_Index == RES_DESKTOP)
++ list.push_back(make_pair(StringUtils::Format("DESKTOP"), resolution->ResInfo_Index));
++else
+ list.push_back(make_pair(
+ StringUtils::Format("%dx%d%s", resolution->width, resolution->height,
+ ModeFlagsToString(resolution->flags, false).c_str()),
+
+From 994c18e9e61d6a1070028f4253b68491e6feb474 Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Sat, 16 Aug 2014 21:01:42 +0100
+Subject: [PATCH 32/61] omxrender: Hacks to reduce GUI rendering rate when
+ playing video
+
+---
+ language/English/strings.po | 27 +++++++++++++++++++++++++++
+ system/settings/rbp.xml | 16 ++++++++++++++++
+ xbmc/Application.cpp | 17 +++++++++++++++++
+ 3 files changed, 60 insertions(+)
+
+diff --git a/language/English/strings.po b/language/English/strings.po
+index 8e67be0..8acc0e9 100755
+--- a/language/English/strings.po
++++ b/language/English/strings.po
+@@ -16125,3 +16125,30 @@ msgstr ""
+ msgctxt "#38021"
+ msgid "Allow viewing and playing files in archives (e.g. zip, rar)"
+ msgstr ""
++
++#: system/settings/settings.xml
++msgctxt "#38000"
++msgid "Limit GUI updates when playing video"
++msgstr ""
++
++#: system/settings/settings.xml
++msgctxt "#38001"
++msgid "This can reduce CPU when playing video by updating the overlays less often"
++msgstr ""
++
++#: system/settings/settings.xml
++msgctxt "#38002"
++msgid "Off"
++msgstr ""
++
++msgctxt "#38003"
++msgid "5 fps"
++msgstr ""
++
++msgctxt "#38004"
++msgid "10 fps"
++msgstr ""
++
++msgctxt "#38005"
++msgid "24 fps"
++msgstr ""
+diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml
+index f3c8a01..2996c29 100644
+--- a/system/settings/rbp.xml
++++ b/system/settings/rbp.xml
+@@ -25,6 +25,22 @@
+
+
+
++
++
++ 2
++ 10
++
++
++
++
++
++
++
++
++
++
++
++
+
+
+
+diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp
+index 4a5619a..70dfea5 100644
+--- a/xbmc/Application.cpp
++++ b/xbmc/Application.cpp
+@@ -2207,6 +2207,23 @@ void CApplication::Render()
+ if (m_bStop)
+ return;
+
++#ifdef TARGET_RASPBERRY_PI
++ if (g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback())
++ {
++ int fps = CSettings::Get().GetInt("videoplayer.limitguiupdate");
++ unsigned int now = XbmcThreads::SystemClockMillis();
++ unsigned int frameTime = now - m_lastFrameTime;
++ if (fps > 0 && frameTime * fps < 1000)
++ {
++ g_renderManager.FrameWait(100);
++ g_infoManager.UpdateFPS();
++ g_renderManager.FrameMove();
++ g_renderManager.FrameFinish();
++ return;
++ }
++ }
++#endif
++
+ MEASURE_FUNCTION;
+
+ int vsync_mode = CSettings::Get().GetInt("videoscreen.vsync");
+
+From dde88c3d2123c6b6036f6d32d546ad691b06a99c Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Tue, 9 Sep 2014 12:04:26 +0100
+Subject: [PATCH 33/61] egl: Treat unknown display aspect ratio as square pixel
+
+---
+ xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp
+index bf1e589..a25eb86 100644
+--- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp
++++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp
+@@ -446,7 +446,7 @@ bool CEGLNativeTypeRaspberryPI::ProbeResolutions(std::vector &r
+ 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 = get_display_aspect_ratio((HDMI_ASPECT_T)tv_state.display.hdmi.display_options.aspect) / ((float)m_desktopRes.iScreenWidth / (float)m_desktopRes.iScreenHeight);
++ 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);
+ // Also add 3D flags
+ if (tv_state.display.hdmi.format_3d == HDMI_3D_FORMAT_SBS_HALF)
+ m_desktopRes.dwFlags |= D3DPRESENTFLAG_MODE3DSBS;
+@@ -467,7 +467,7 @@ bool CEGLNativeTypeRaspberryPI::ProbeResolutions(std::vector &r
+ m_desktopRes.iScreenHeight= tv_state.display.sdtv.height;
+ m_desktopRes.dwFlags = D3DPRESENTFLAG_INTERLACED;
+ m_desktopRes.fRefreshRate = (float)tv_state.display.sdtv.frame_rate;
+- m_desktopRes.fPixelRatio = get_display_aspect_ratio((SDTV_ASPECT_T)tv_state.display.sdtv.display_options.aspect) / ((float)m_desktopRes.iScreenWidth / (float)m_desktopRes.iScreenHeight);
++ 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);
+
+From a3efced6244577f10cbdaf5c16a3a5eee627e519 Mon Sep 17 00:00:00 2001
+From: anaconda
+Date: Thu, 11 Sep 2014 21:30:43 +0200
+Subject: [PATCH 34/61] Disable textbox autoscrolling while on screensaver.
+
+SQUASH: only if dim or black
+---
+ xbmc/Application.cpp | 7 +++++++
+ xbmc/Application.h | 2 ++
+ xbmc/guilib/GUITextBox.cpp | 5 ++++-
+ 3 files changed, 13 insertions(+), 1 deletion(-)
+
+diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp
+index 70dfea5..a5706bd 100644
+--- a/xbmc/Application.cpp
++++ b/xbmc/Application.cpp
+@@ -5881,3 +5881,10 @@ void CApplication::CloseNetworkShares()
+ CSFTPSessionManager::DisconnectAllSessions();
+ #endif
+ }
++
++std::string CApplication::GetScreenSaverId()
++{
++ if (m_screenSaver)
++ return m_screenSaver->ID();
++ return "";
++}
+diff --git a/xbmc/Application.h b/xbmc/Application.h
+index 0a332ff..15efc90 100644
+--- a/xbmc/Application.h
++++ b/xbmc/Application.h
+@@ -380,6 +380,8 @@ class CApplication : public CXBApplicationEx, public IPlayerCallback, public IMs
+
+ void SetLoggingIn(bool loggingIn) { m_loggingIn = loggingIn; }
+
++ std::string GetScreenSaverId();
++
+ protected:
+ virtual bool OnSettingsSaving() const;
+
+diff --git a/xbmc/guilib/GUITextBox.cpp b/xbmc/guilib/GUITextBox.cpp
+index c0e2fa5..0eca360 100644
+--- a/xbmc/guilib/GUITextBox.cpp
++++ b/xbmc/guilib/GUITextBox.cpp
+@@ -23,6 +23,7 @@
+ #include "utils/XBMCTinyXML.h"
+ #include "utils/MathUtils.h"
+ #include "utils/StringUtils.h"
++#include "Application.h"
+
+ using namespace std;
+
+@@ -132,7 +133,9 @@ void CGUITextBox::Process(unsigned int currentTime, CDirtyRegionList &dirtyregio
+ // update our auto-scrolling as necessary
+ if (m_autoScrollTime && m_lines.size() > m_itemsPerPage)
+ {
+- if (!m_autoScrollCondition || m_autoScrollCondition->Get())
++ if ((!m_autoScrollCondition || m_autoScrollCondition->Get()) && !(g_application.IsInScreenSaver() &&
++ (g_application.GetScreenSaverId() == "screensaver.xbmc.builtin.black" ||
++ g_application.GetScreenSaverId() == "screensaver.xbmc.builtin.dim")))
+ {
+ if (m_lastRenderTime)
+ m_autoScrollDelayTime += currentTime - m_lastRenderTime;
+
+From d2bfba18dd090634d5725ae74e92e6de7792fca7 Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Thu, 18 Sep 2014 14:24:56 +0100
+Subject: [PATCH 35/61] [omxplayer] Only enable audio clock master when A/V
+ sync method is set to audio clock
+
+---
+ xbmc/cores/omxplayer/OMXAudio.cpp | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/xbmc/cores/omxplayer/OMXAudio.cpp b/xbmc/cores/omxplayer/OMXAudio.cpp
+index 5475570..7c07b57 100644
+--- a/xbmc/cores/omxplayer/OMXAudio.cpp
++++ b/xbmc/cores/omxplayer/OMXAudio.cpp
+@@ -246,7 +246,8 @@ bool COMXAudio::PortSettingsChanged()
+ {
+ // By default audio_render is the clock master, and if output samples don't fit the timestamps, it will speed up/slow down the clock.
+ // This tends to be better for maintaining audio sync and avoiding audio glitches, but can affect video/display sync
+- if(CSettings::Get().GetBool("videoplayer.usedisplayasclock") || CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both")
++ if((CSettings::Get().GetBool("videoplayer.usedisplayasclock") && CSettings::Get().GetInt("videoplayer.synctype") == SYNC_DISCON) ||
++ CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Both")
+ {
+ OMX_CONFIG_BOOLEANTYPE configBool;
+ OMX_INIT_STRUCTURE(configBool);
+@@ -272,7 +273,7 @@ bool COMXAudio::PortSettingsChanged()
+ {
+ // By default audio_render is the clock master, and if output samples don't fit the timestamps, it will speed up/slow down the clock.
+ // This tends to be better for maintaining audio sync and avoiding audio glitches, but can affect video/display sync
+- if(CSettings::Get().GetBool("videoplayer.usedisplayasclock"))
++ if(CSettings::Get().GetBool("videoplayer.usedisplayasclock") && CSettings::Get().GetInt("videoplayer.synctype") == SYNC_DISCON)
+ {
+ OMX_CONFIG_BOOLEANTYPE configBool;
+ OMX_INIT_STRUCTURE(configBool);
+
+From 165d1b6f807277a808f70537d5f3bb2db75c3592 Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Fri, 19 Sep 2014 11:54:49 +0100
+Subject: [PATCH 36/61] [dvdplayer/rbp] Add pi specific option to maintain
+ vsync with pll adjustment
+
+New A/V sync option in settings/video/playback to do "Adjust PLL".
+This uses video clock (so perfect video syncing) but avoids having to resample
+or drop/dupe audio packets which is normally required.
+
+Needed updated firmware
+---
+ language/English/strings.po | 5 +++++
+ system/settings/rbp.xml | 20 ++++++++++++++++++
+ xbmc/cores/AudioEngine/Utils/AEUtil.h | 3 ++-
+ xbmc/cores/dvdplayer/DVDPlayerAudio.cpp | 36 +++++++++++++++++++++++++++++++--
+ xbmc/cores/dvdplayer/DVDPlayerAudio.h | 1 +
+ xbmc/linux/RBP.cpp | 14 +++++++++++++
+ xbmc/linux/RBP.h | 1 +
+ 7 files changed, 77 insertions(+), 3 deletions(-)
+
+diff --git a/language/English/strings.po b/language/English/strings.po
+index 8acc0e9..a3b71e8 100755
+--- a/language/English/strings.po
++++ b/language/English/strings.po
+@@ -16152,3 +16152,8 @@ msgstr ""
+ msgctxt "#38005"
+ msgid "24 fps"
+ msgstr ""
++
++#: system/settings/settings.xml
++msgctxt "#38006"
++msgid "Adjust PLL"
++msgstr ""
+diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml
+index 2996c29..79853a8 100644
+--- a/system/settings/rbp.xml
++++ b/system/settings/rbp.xml
+@@ -11,6 +11,26 @@
+
+
+
++
++
++
++ 2
++ 2
++
++
++
++
++
++
++
++
++
++ true
++
++
++
++
++
+
+
+ false
+diff --git a/xbmc/cores/AudioEngine/Utils/AEUtil.h b/xbmc/cores/AudioEngine/Utils/AEUtil.h
+index 782a9ba..3e0390c 100644
+--- a/xbmc/cores/AudioEngine/Utils/AEUtil.h
++++ b/xbmc/cores/AudioEngine/Utils/AEUtil.h
+@@ -57,7 +57,8 @@ enum AVSync
+ {
+ SYNC_DISCON = 0,
+ SYNC_SKIPDUP,
+- SYNC_RESAMPLE
++ SYNC_RESAMPLE,
++ SYNC_PLLADJUST
+ };
+
+ struct AEDelayStatus
+diff --git a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp
+index c1a5b8d..fe76917 100644
+--- a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp
++++ b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp
+@@ -113,6 +113,7 @@ CDVDPlayerAudio::CDVDPlayerAudio(CDVDClock* pClock, CDVDMessageQueue& parent)
+ m_started = false;
+ m_silence = false;
+ m_resampleratio = 1.0;
++ m_plladjust = 1.0f;
+ m_synctype = SYNC_DISCON;
+ m_setsynctype = SYNC_DISCON;
+ m_prevsynctype = -1;
+@@ -475,6 +476,8 @@ void CDVDPlayerAudio::UpdatePlayerInfo()
+ //if the resample ratio is 0.5, then we're playing twice as fast
+ if (m_synctype == SYNC_RESAMPLE)
+ s << ", rr:" << fixed << setprecision(5) << 1.0 / m_resampleratio;
++ if (m_synctype == SYNC_PLLADJUST)
++ s << ", pll:" << fixed << setprecision(5) << 1.0 / m_plladjust;
+
+ s << ", att:" << fixed << setprecision(1) << log(GetCurrentAttenuation()) * 20.0f << " dB";
+
+@@ -627,8 +630,8 @@ void CDVDPlayerAudio::SetSyncType(bool passthrough)
+
+ if (m_synctype != m_prevsynctype)
+ {
+- const char *synctypes[] = {"clock feedback", "skip/duplicate", "resample", "invalid"};
+- int synctype = (m_synctype >= 0 && m_synctype <= 2) ? m_synctype : 3;
++ const char *synctypes[] = {"clock feedback", "skip/duplicate", "resample", "pll adjust", "invalid"};
++ int synctype = (m_synctype >= 0 && m_synctype <= 3) ? m_synctype : 4;
+ CLog::Log(LOGDEBUG, "CDVDPlayerAudio:: synctype set to %i: %s", m_synctype, synctypes[synctype]);
+ m_prevsynctype = m_synctype;
+ }
+@@ -702,6 +705,31 @@ void CDVDPlayerAudio::HandleSyncError(double duration)
+ }
+ m_resampleratio = 1.0 / m_pClock->GetClockSpeed() + proportional + m_integral;
+ }
++ else if (m_synctype == SYNC_PLLADJUST)
++ {
++#if defined(TARGET_RASPBERRY_PI)
++ //reset the integral on big errors, failsafe
++ if (fabs(m_error) > DVD_TIME_BASE)
++ m_integral = 0;
++ else if (fabs(m_error) > DVD_MSEC_TO_TIME(5))
++ m_integral += m_error / DVD_TIME_BASE / INTEGRAL;
++
++ double proportional = 0.0;
++
++ //on big errors use more proportional
++ if (fabs(m_error / DVD_TIME_BASE) > 0.0)
++ {
++ double proportionaldiv = PROPORTIONAL * (PROPREF / fabs(m_error / DVD_TIME_BASE));
++ if (proportionaldiv < PROPDIVMIN) proportionaldiv = PROPDIVMIN;
++ else if (proportionaldiv > PROPDIVMAX) proportionaldiv = PROPDIVMAX;
++
++ proportional = m_error / DVD_TIME_BASE / proportionaldiv;
++ }
++ m_plladjust = 1.0 / m_pClock->GetClockSpeed() + proportional + m_integral;
++ double new_adjust = g_RBP.AdjustHDMIClock(m_plladjust);
++ CLog::Log(LOGDEBUG, "CDVDPlayerAudio::%s pll:%.4f (%.4f) proportional:%.4f integral:%.4f", __FUNCTION__, m_plladjust, new_adjust, proportional, m_integral);
++#endif
++ }
+ }
+ }
+
+@@ -740,6 +768,10 @@ bool CDVDPlayerAudio::OutputPacket(DVDAudioFrame &audioframe)
+ m_dvdAudio.SetResampleRatio(m_resampleratio);
+ m_dvdAudio.AddPackets(audioframe);
+ }
++ else if (m_synctype == SYNC_PLLADJUST)
++ {
++ m_dvdAudio.AddPackets(audioframe);
++ }
+
+ return true;
+ }
+diff --git a/xbmc/cores/dvdplayer/DVDPlayerAudio.h b/xbmc/cores/dvdplayer/DVDPlayerAudio.h
+index e8b2ab6..02c64a0 100644
+--- a/xbmc/cores/dvdplayer/DVDPlayerAudio.h
++++ b/xbmc/cores/dvdplayer/DVDPlayerAudio.h
+@@ -232,6 +232,7 @@ class CDVDPlayerAudio : public CThread, public IDVDStreamPlayerAudio
+ bool m_prevskipped;
+ double m_maxspeedadjust;
+ double m_resampleratio; //resample ratio when using SYNC_RESAMPLE, used for the codec info
++ double m_plladjust; // for display using SYNC_PLLADJUST
+
+ struct SInfo
+ {
+diff --git a/xbmc/linux/RBP.cpp b/xbmc/linux/RBP.cpp
+index 5119949..ce09fce 100644
+--- a/xbmc/linux/RBP.cpp
++++ b/xbmc/linux/RBP.cpp
+@@ -212,4 +212,18 @@ void CRBP::Deinitialize()
+ m_initialized = false;
+ m_omx_initialized = false;
+ }
++
++double CRBP::AdjustHDMIClock(double adjust)
++{
++ char response[80];
++ vc_gencmd(response, sizeof response, "hdmi_adjust_clock %f", adjust);
++ float new_adjust = 1.0f;
++ char *p = strchr(response, '=');
++ if (p)
++ new_adjust = atof(p+1);
++ CLog::Log(LOGDEBUG, "CRBP::%s(%.4f) = %.4f", __func__, adjust, new_adjust);
++ return new_adjust;
++}
++
++
+ #endif
+diff --git a/xbmc/linux/RBP.h b/xbmc/linux/RBP.h
+index 4fd18f3..6456657 100644
+--- a/xbmc/linux/RBP.h
++++ b/xbmc/linux/RBP.h
+@@ -58,6 +58,7 @@ class CRBP
+ unsigned char *CaptureDisplay(int width, int height, int *stride, bool swap_red_blue, bool video_only = true);
+ DllOMX *GetDllOMX() { return m_OMX ? m_OMX->GetDll() : NULL; }
+ void WaitVsync();
++ double AdjustHDMIClock(double adjust);
+
+ private:
+ DllBcmHost *m_DllBcmHost;
+
+From 797d4926183f165a74a9b84ab3d3369907222c6b Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Sat, 27 Sep 2014 15:32:37 +0100
+Subject: [PATCH 37/61] [dvdplayer] exerimental: don't raise priority of audio
+ thread
+
+---
+ xbmc/cores/dvdplayer/DVDPlayer.cpp | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp
+index 12a3ed6..cb512ed 100644
+--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp
++++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp
+@@ -3210,7 +3210,11 @@ bool CDVDPlayer::OpenAudioStream(CDVDStreamInfo& hint, bool reset)
+ m_dvdPlayerAudio->SendMessage(new CDVDMsg(CDVDMsg::PLAYER_STARTED), 1);
+
+ /* audio normally won't consume full cpu, so let it have prio */
++#ifdef TARGET_RASPBERRY_PI
++ m_dvdPlayerAudio->SetPriority(GetPriority());
++#else
+ m_dvdPlayerAudio->SetPriority(GetPriority()+1);
++#endif
+ return true;
+ }
+
+
+From 084de6d589287fed574658f9eec2180b0d7a7c79 Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Sun, 28 Sep 2014 19:28:17 +0100
+Subject: [PATCH 38/61] [mmalcodec] Introduce a preroll period to buffer up
+ frames on startup
+
+---
+ .../DVDCodecs/Video/DVDVideoCodecMMAL.cpp | 5 ++++
+ .../dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.h | 1 +
+ xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 30 +++++++++++++++++-----
+ xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h | 3 +++
+ 4 files changed, 33 insertions(+), 6 deletions(-)
+
+diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.cpp
+index 55b9969..262283d 100644
+--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.cpp
++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.cpp
+@@ -96,4 +96,9 @@ bool CDVDVideoCodecMMAL::GetCodecStats(double &pts, int &droppedPics)
+ return m_decoder->GetCodecStats(pts, droppedPics);
+ }
+
++void CDVDVideoCodecMMAL::SetSpeed(int iSpeed)
++{
++ m_decoder->SetSpeed(iSpeed);
++}
++
+ #endif
+diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.h
+index 67aa505..a768e70 100644
+--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.h
++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecMMAL.h
+@@ -42,6 +42,7 @@ class CDVDVideoCodecMMAL : public CDVDVideoCodec
+ virtual void SetDropState(bool bDrop);
+ virtual const char* GetName(void);
+ virtual bool GetCodecStats(double &pts, int &droppedPics);
++ virtual void SetSpeed(int iSpeed);
+
+ protected:
+ MMALVideoPtr m_decoder;
+diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp
+index 098910e..6742e0e 100644
+--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp
++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp
+@@ -128,6 +128,8 @@ CMMALVideo::CMMALVideo()
+ m_output_busy = 0;
+ m_demux_queue_length = 0;
+ m_es_format = mmal_format_alloc();
++ m_preroll = true;
++ m_speed = DVD_PLAYSPEED_NORMAL;
+ }
+
+ CMMALVideo::~CMMALVideo()
+@@ -696,6 +698,8 @@ bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, MMALVide
+
+ m_drop_state = false;
+ m_startframe = false;
++ m_preroll = !m_hints.stills;
++ m_speed = DVD_PLAYSPEED_NORMAL;
+
+ return true;
+ }
+@@ -904,23 +908,29 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts)
+ break;
+ }
+ int ret = 0;
+- if (!m_output_ready.empty())
++ if (mmal_queue_length(m_dec_input_pool->queue) > 0 && !m_demux_queue_length)
+ {
+ if (g_advancedSettings.CanLogComponent(LOGVIDEO))
+ CLog::Log(LOGDEBUG, "%s::%s - got space for output: demux_queue(%d) space(%d)", CLASSNAME, __func__, m_demux_queue_length, mmal_queue_length(m_dec_input_pool->queue) * m_dec_input->buffer_size);
+- ret |= VC_PICTURE;
++ ret |= VC_BUFFER;
+ }
+- if (mmal_queue_length(m_dec_input_pool->queue) > 0 && !m_demux_queue_length)
++ else
++ m_preroll = false;
++
++ if (m_preroll && m_output_ready.size() >= GetAllowedReferences())
++ m_preroll = false;
++
++ if (!m_output_ready.empty() && !m_preroll)
+ {
+ if (g_advancedSettings.CanLogComponent(LOGVIDEO))
+ CLog::Log(LOGDEBUG, "%s::%s - got output picture:%d", CLASSNAME, __func__, m_output_ready.size());
+- ret |= VC_BUFFER;
++ ret |= VC_PICTURE;
+ }
+ if (!ret)
+ {
+ if (g_advancedSettings.CanLogComponent(LOGVIDEO))
+- CLog::Log(LOGDEBUG, "%s::%s - Nothing to do: dts_queue(%d) ready_queue(%d) busy_queue(%d) demux_queue(%d) space(%d)",
+- CLASSNAME, __func__, m_dts_queue.size(), m_output_ready.size(), m_output_busy, m_demux_queue_length, mmal_queue_length(m_dec_input_pool->queue) * m_dec_input->buffer_size);
++ CLog::Log(LOGDEBUG, "%s::%s - Nothing to do: dts_queue(%d) ready_queue(%d) busy_queue(%d) demux_queue(%d) space(%d) preroll(%d)",
++ CLASSNAME, __func__, m_dts_queue.size(), m_output_ready.size(), m_output_busy, m_demux_queue_length, mmal_queue_length(m_dec_input_pool->queue) * m_dec_input->buffer_size, m_preroll);
+ Sleep(10); // otherwise we busy spin
+ }
+ return ret;
+@@ -963,8 +973,16 @@ void CMMALVideo::Reset(void)
+ m_decoderPts = DVD_NOPTS_VALUE;
+ m_droppedPics = 0;
+ m_decode_frame_number = 1;
++ m_preroll = !m_hints.stills && (m_speed == DVD_PLAYSPEED_NORMAL || m_speed == DVD_PLAYSPEED_PAUSE);
+ }
+
++void CMMALVideo::SetSpeed(int iSpeed)
++{
++ if (g_advancedSettings.CanLogComponent(LOGVIDEO))
++ CLog::Log(LOGDEBUG, "%s::%s %d->%d", CLASSNAME, __func__, m_speed, iSpeed);
++
++ m_speed = iSpeed;
++}
+
+ void CMMALVideo::ReturnBuffer(CMMALVideoBuffer *buffer)
+ {
+diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h
+index b4aa571..4f81bbd 100644
+--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h
++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h
+@@ -90,6 +90,7 @@ class CMMALVideo
+ virtual void SetDropState(bool bDrop);
+ virtual const char* GetName(void) { return (const char*)m_pFormatName; }
+ virtual bool GetCodecStats(double &pts, int &droppedPics);
++ virtual void SetSpeed(int iSpeed);
+
+ // MMAL decoder callback routines.
+ void ReleaseBuffer(CMMALVideoBuffer *buffer);
+@@ -140,6 +141,8 @@ class CMMALVideo
+ unsigned int m_decode_frame_number;
+ double m_decoderPts;
+ unsigned int m_droppedPics;
++ int m_speed;
++ bool m_preroll;
+
+ MMAL_COMPONENT_T *m_dec;
+ MMAL_PORT_T *m_dec_input;
+
+From 46d39ba5ad0927c5d61712a8b04f8d3ca824d9fd Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Wed, 24 Sep 2014 23:13:52 +0100
+Subject: [PATCH 39/61] [audio] Add settings option to boost centre channel
+ when downmixing
+
+This allows a dB volume increase to be added to centre channel.
+This can help improve dialgue in the presence of background music/effects.
+It can go up to 30dB for testing purposes, but value of 6 is probably more reasonable.
+It is recommended to ensure "Normalise levels on downmix" is enabled when boosting by large values to avoid clipping.
+
+Should work with Pi Sink (dvdplayer/paplayer) and omxplayer
+---
+ language/English/strings.po | 15 +++++++++++++++
+ system/settings/settings.xml | 12 ++++++++++++
+ .../Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp | 7 +++++++
+ .../AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp | 6 ++++++
+ xbmc/cores/omxplayer/OMXAudio.cpp | 6 ++++++
+ 5 files changed, 46 insertions(+)
+
+diff --git a/language/English/strings.po b/language/English/strings.po
+index a3b71e8..24f9636 100755
+--- a/language/English/strings.po
++++ b/language/English/strings.po
+@@ -16157,3 +16157,18 @@ msgstr ""
+ msgctxt "#38006"
+ msgid "Adjust PLL"
+ msgstr ""
++
++#: system/settings/settings.xml
++msgctxt "#38007"
++msgid "Boost centre channel when downmixing"
++msgstr ""
++
++#: system/settings/settings.xml
++msgctxt "#38008"
++msgid "Increase this value to make the dialogue louder compared to background sounds when downmixing multichannel audio"
++msgstr ""
++
++#: system/settings/settings.xml
++msgctxt "#38009"
++msgid "%i dB"
++msgstr ""
+diff --git a/system/settings/settings.xml b/system/settings/settings.xml
+index 0db66a2..dbddcb6 100644
+--- a/system/settings/settings.xml
++++ b/system/settings/settings.xml
+@@ -2451,6 +2451,18 @@
+ true
+
+
++
++ 2
++ 0
++
++ 0
++ 1
++ 30
++
++
++ 38009
++
++
+
+ HAS_AE_QUALITY_LEVELS
+ 2
+diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp
+index de188e7..449a500 100644
+--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp
++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp
+@@ -20,6 +20,7 @@
+
+ #include "cores/AudioEngine/Utils/AEUtil.h"
+ #include "ActiveAEResampleFFMPEG.h"
++#include "settings/Settings.h"
+ #include "utils/log.h"
+
+ extern "C" {
+@@ -105,6 +106,12 @@ bool CActiveAEResampleFFMPEG::Init(uint64_t dst_chan_layout, int dst_channels, i
+ {
+ av_opt_set_double(m_pContext, "rematrix_maxval", 1.0, 0);
+ }
++ int boost_center = CSettings::Get().GetInt("audiooutput.boostcenter");
++ if (boost_center)
++ {
++ float gain = pow(10.0f, ((float)(-3 + boost_center))/20.0f);
++ av_opt_set_double(m_pContext, "center_mix_level", gain, 0);
++ }
+
+ if (remapLayout)
+ {
+diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp
+index 96f79b7..84505bf 100644
+--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp
++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp
+@@ -162,6 +162,12 @@ bool CActiveAEResamplePi::Init(uint64_t dst_chan_layout, int dst_channels, int d
+ {
+ av_opt_set_double(m_pContext, "rematrix_maxval", 1.0, 0);
+ }
++ int boost_center = CSettings::Get().GetInt("audiooutput.boostcenter");
++ if (boost_center)
++ {
++ float gain = pow(10.0f, ((float)(-3 + boost_center))/20.0f);
++ av_opt_set_double(m_pContext, "center_mix_level", gain, 0);
++ }
+
+ if (remapLayout)
+ {
+diff --git a/xbmc/cores/omxplayer/OMXAudio.cpp b/xbmc/cores/omxplayer/OMXAudio.cpp
+index 7c07b57..ef4c3d4 100644
+--- a/xbmc/cores/omxplayer/OMXAudio.cpp
++++ b/xbmc/cores/omxplayer/OMXAudio.cpp
+@@ -633,6 +633,12 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo
+ {
+ av_opt_set_double(m_pContext, "rematrix_maxval", 1.0, 0);
+ }
++ int boost_center = CSettings::Get().GetInt("audiooutput.boostcenter");
++ if (boost_center)
++ {
++ float gain = pow(10.0f, ((float)(-3 + boost_center))/20.0f);
++ av_opt_set_double(m_pContext, "center_mix_level", gain, 0);
++ }
+
+ // stereo upmix
+ if (upmix && m_src_channels == 2 && m_dst_channels > 2)
+
+From 6686f4f39283921d069464eec0652f0cf6b091b0 Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Fri, 3 Oct 2014 18:38:07 +0100
+Subject: [PATCH 40/61] [omxcore] Skip out of flush on error
+
+---
+ xbmc/linux/OMXCore.cpp | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/xbmc/linux/OMXCore.cpp b/xbmc/linux/OMXCore.cpp
+index 4ae29ba..4caa304 100644
+--- a/xbmc/linux/OMXCore.cpp
++++ b/xbmc/linux/OMXCore.cpp
+@@ -419,7 +419,7 @@ void COMXCoreComponent::FlushAll()
+
+ void COMXCoreComponent::FlushInput()
+ {
+- if(!m_handle)
++ if(!m_handle || m_resource_error)
+ return;
+
+ OMX_ERRORTYPE omx_err = OMX_ErrorNone;
+@@ -436,7 +436,7 @@ void COMXCoreComponent::FlushInput()
+
+ void COMXCoreComponent::FlushOutput()
+ {
+- if(!m_handle)
++ if(!m_handle || m_resource_error)
+ return;
+
+ OMX_ERRORTYPE omx_err = OMX_ErrorNone;
+
+From eb1c477c0c592f29037a9b14a30e5c23f79b9af4 Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Fri, 3 Oct 2014 18:40:06 +0100
+Subject: [PATCH 41/61] [SinkPi] Handle multichannel layout more like OMXAudio
+
+---
+ xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp
+index 89684e4..fd9a03d 100644
+--- a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp
++++ b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp
+@@ -92,9 +92,9 @@ static void SetAudioProps(bool stream_channels, uint32_t channel_map)
+ CLog::Log(LOGDEBUG, "%s:%s hdmi_stream_channels %d hdmi_channel_map %08x", CLASSNAME, __func__, stream_channels, channel_map);
+ }
+
+-static uint32_t GetChannelMap(AEAudioFormat &format, bool passthrough)
++static uint32_t GetChannelMap(const CAEChannelInfo &channelLayout, bool passthrough)
+ {
+- unsigned int channels = format.m_channelLayout.Count();
++ unsigned int channels = channelLayout.Count();
+ uint32_t channel_map = 0;
+ if (passthrough)
+ return 0;
+@@ -133,12 +133,12 @@ static uint32_t GetChannelMap(AEAudioFormat &format, bool passthrough)
+ // According to CEA-861-D only RL and RR are known. In case of a format having SL and SR channels
+ // but no BR BL channels, we use the wide map in order to open only the num of channels really
+ // needed.
+- if (format.m_channelLayout.HasChannel(AE_CH_BL) && !format.m_channelLayout.HasChannel(AE_CH_SL))
++ if (channelLayout.HasChannel(AE_CH_BL) && !channelLayout.HasChannel(AE_CH_SL))
+ map = map_back;
+
+ for (unsigned int i = 0; i < channels; ++i)
+ {
+- AEChannel c = format.m_channelLayout[i];
++ AEChannel c = channelLayout[i];
+ unsigned int chan = 0;
+ if ((unsigned int)c < sizeof map_normal / sizeof *map_normal)
+ chan = map[(unsigned int)c];
+@@ -169,9 +169,9 @@ static uint32_t GetChannelMap(AEAudioFormat &format, bool passthrough)
+ 0xff, // 7
+ 0x13, // 7.1
+ };
+- uint8_t cea = format.m_channelLayout.HasChannel(AE_CH_LFE) ? cea_map_lfe[channels] : cea_map[channels];
++ uint8_t cea = channelLayout.HasChannel(AE_CH_LFE) ? cea_map_lfe[channels] : cea_map[channels];
+ if (cea == 0xff)
+- CLog::Log(LOGERROR, "%s::%s - Unexpected CEA mapping %d,%d", CLASSNAME, __func__, format.m_channelLayout.HasChannel(AE_CH_LFE), channels);
++ CLog::Log(LOGERROR, "%s::%s - Unexpected CEA mapping %d,%d", CLASSNAME, __func__, channelLayout.HasChannel(AE_CH_LFE), channels);
+
+ channel_map |= cea << 24;
+
+@@ -208,7 +208,7 @@ bool CAESinkPi::Initialize(AEAudioFormat &format, std::string &device)
+ format.m_frames = format.m_sampleRate * AUDIO_PLAYBUFFER / NUM_OMX_BUFFERS;
+ format.m_frameSamples = format.m_frames * channels;
+
+- SetAudioProps(m_passthrough, GetChannelMap(format, m_passthrough));
++ SetAudioProps(m_passthrough, GetChannelMap(format.m_channelLayout, m_passthrough));
+
+ m_format = format;
+ m_sinkbuffer_sec_per_byte = 1.0 / (double)(m_format.m_frameSize * m_format.m_sampleRate);
+
+From da6a81c9c7104c0d99f1140e14cf5b97efbd670a Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Mon, 27 Oct 2014 15:23:51 +0000
+Subject: [PATCH 42/61] [rbp] Default extract thumbnails to false
+
+It can take 80 seconds for a single file on a Pi. It can cause crashes with out-of-memory errors.
+It genereates a lot of support issues. Best to default to disabled and let users enable it if they must
+---
+ system/settings/rbp.xml | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml
+index 79853a8..4c2ef41 100644
+--- a/system/settings/rbp.xml
++++ b/system/settings/rbp.xml
+@@ -62,6 +62,16 @@
+
+
+
++
++
++
++
++
++
+
+
+
+
+From c6be72242c0a7b7460f6c319c47e553151069a5a Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Tue, 11 Nov 2014 18:14:23 +0000
+Subject: [PATCH 43/61] [resamplepi] Try to report the same numbers as ffmpeg
+
+---
+ .../cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp
+index 84505bf..2b5bef2 100644
+--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp
++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp
+@@ -544,9 +544,10 @@ int CActiveAEResamplePi::Resample(uint8_t **dst_buffer, int dst_samples, uint8_t
+
+ int64_t CActiveAEResamplePi::GetDelay(int64_t base)
+ {
+- int ret = m_dst_rate ? 1000 * GetBufferedSamples() / m_dst_rate : 0;
++ int64_t ret = av_rescale_rnd(GetBufferedSamples(), m_dst_rate, base, AV_ROUND_UP);
++
+ #ifdef DEBUG_VERBOSE
+- CLog::Log(LOGINFO, "%s::%s = %d", CLASSNAME, __func__, ret);
++ CLog::Log(LOGINFO, "%s::%s = %d", CLASSNAME, __func__, (int)ret);
+ #endif
+ return ret;
+ }
+@@ -567,7 +568,7 @@ int CActiveAEResamplePi::GetBufferedSamples()
+
+ int CActiveAEResamplePi::CalcDstSampleCount(int src_samples, int dst_rate, int src_rate)
+ {
+- int ret = ((long long)src_samples * dst_rate + src_rate-1) / src_rate;
++ int ret = av_rescale_rnd(src_samples, dst_rate, src_rate, AV_ROUND_UP);
+ #ifdef DEBUG_VERBOSE
+ CLog::Log(LOGINFO, "%s::%s = %d", CLASSNAME, __func__, ret);
+ #endif
+@@ -576,7 +577,7 @@ int CActiveAEResamplePi::CalcDstSampleCount(int src_samples, int dst_rate, int s
+
+ int CActiveAEResamplePi::GetSrcBufferSize(int samples)
+ {
+- int ret = 0;
++ int ret = av_samples_get_buffer_size(NULL, m_src_channels, samples, m_src_fmt, 1);
+ #ifdef DEBUG_VERBOSE
+ CLog::Log(LOGINFO, "%s::%s = %d", CLASSNAME, __func__, ret);
+ #endif
+@@ -585,7 +586,7 @@ int CActiveAEResamplePi::GetSrcBufferSize(int samples)
+
+ int CActiveAEResamplePi::GetDstBufferSize(int samples)
+ {
+- int ret = CalcDstSampleCount(samples, m_dst_rate, m_src_rate);
++ int ret = av_samples_get_buffer_size(NULL, m_dst_channels, samples, m_dst_fmt, 1);
+ #ifdef DEBUG_VERBOSE
+ CLog::Log(LOGINFO, "%s::%s = %d", CLASSNAME, __func__, ret);
+ #endif
+
+From 966d1486cb16fd2bb43aae9a5f494594687f697a Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Tue, 11 Nov 2014 20:49:30 +0000
+Subject: [PATCH 44/61] [dvdplayer] New scheme for PLL adjustment for video
+ clock
+
+---
+ xbmc/cores/dvdplayer/DVDPlayerAudio.cpp | 40 +++++++++++++--------------------
+ xbmc/cores/dvdplayer/DVDPlayerAudio.h | 2 ++
+ 2 files changed, 18 insertions(+), 24 deletions(-)
+
+diff --git a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp
+index fe76917..4f25feb 100644
+--- a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp
++++ b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp
+@@ -113,7 +113,9 @@ CDVDPlayerAudio::CDVDPlayerAudio(CDVDClock* pClock, CDVDMessageQueue& parent)
+ m_started = false;
+ m_silence = false;
+ m_resampleratio = 1.0;
+- m_plladjust = 1.0f;
++ m_plladjust = 1.0;
++ m_last_plladjust = 1.0;
++ m_last_error = 0.0;
+ m_synctype = SYNC_DISCON;
+ m_setsynctype = SYNC_DISCON;
+ m_prevsynctype = -1;
+@@ -192,6 +194,8 @@ void CDVDPlayerAudio::OpenStream( CDVDStreamInfo &hints, CDVDAudioCodec* codec )
+
+ m_error = 0;
+ m_errors.Flush();
++ m_plladjust = 1.0;
++ m_last_plladjust = 1.0;
+ m_integral = 0;
+ m_prevskipped = false;
+ m_syncclock = true;
+@@ -234,7 +238,6 @@ void CDVDPlayerAudio::CloseStream(bool bWaitForBuffers)
+
+ // uninit queue
+ m_messageQueue.End();
+-
+ CLog::Log(LOGNOTICE, "Deleting audio codec");
+ if (m_pAudioCodec)
+ {
+@@ -475,9 +478,11 @@ void CDVDPlayerAudio::UpdatePlayerInfo()
+ //print the inverse of the resample ratio, since that makes more sense
+ //if the resample ratio is 0.5, then we're playing twice as fast
+ if (m_synctype == SYNC_RESAMPLE)
+- s << ", rr:" << fixed << setprecision(5) << 1.0 / m_resampleratio;
++ s << ", rr:" << fixed << setprecision(5) << 1.0 / m_resampleratio << ", err:" << fixed << setprecision(1) << m_last_error * 1e-3 << "ms";
++ if (m_synctype == SYNC_SKIPDUP)
++ s << ", err:" << fixed << setprecision(1) << m_last_error * 1e-3 << "ms";
+ if (m_synctype == SYNC_PLLADJUST)
+- s << ", pll:" << fixed << setprecision(5) << 1.0 / m_plladjust;
++ s << ", pll:" << fixed << setprecision(5) << m_last_plladjust << ", err:" << fixed << setprecision(1) << m_last_error * 1e-3 << "ms";
+
+ s << ", att:" << fixed << setprecision(1) << log(GetCurrentAttenuation()) * 20.0f << " dB";
+
+@@ -651,6 +656,7 @@ void CDVDPlayerAudio::HandleSyncError(double duration)
+ m_pClock->Update(clock+error, absolute, 0.0, "CDVDPlayerAudio::HandleSyncError1");
+ m_errors.Flush();
+ m_error = 0;
++ m_plladjust = 1.0;
+ m_syncclock = false;
+
+ return;
+@@ -704,32 +710,18 @@ void CDVDPlayerAudio::HandleSyncError(double duration)
+ proportional = m_error / DVD_TIME_BASE / proportionaldiv;
+ }
+ m_resampleratio = 1.0 / m_pClock->GetClockSpeed() + proportional + m_integral;
++ CLog::Log(LOGDEBUG, "CDVDPlayerAudio::%s rr:%.5f error:%.3fms", __FUNCTION__, m_resampleratio, m_error * 1e-3);
+ }
+ else if (m_synctype == SYNC_PLLADJUST)
+ {
+ #if defined(TARGET_RASPBERRY_PI)
+- //reset the integral on big errors, failsafe
+- if (fabs(m_error) > DVD_TIME_BASE)
+- m_integral = 0;
+- else if (fabs(m_error) > DVD_MSEC_TO_TIME(5))
+- m_integral += m_error / DVD_TIME_BASE / INTEGRAL;
+-
+- double proportional = 0.0;
+-
+- //on big errors use more proportional
+- if (fabs(m_error / DVD_TIME_BASE) > 0.0)
+- {
+- double proportionaldiv = PROPORTIONAL * (PROPREF / fabs(m_error / DVD_TIME_BASE));
+- if (proportionaldiv < PROPDIVMIN) proportionaldiv = PROPDIVMIN;
+- else if (proportionaldiv > PROPDIVMAX) proportionaldiv = PROPDIVMAX;
+-
+- proportional = m_error / DVD_TIME_BASE / proportionaldiv;
+- }
+- m_plladjust = 1.0 / m_pClock->GetClockSpeed() + proportional + m_integral;
+- double new_adjust = g_RBP.AdjustHDMIClock(m_plladjust);
+- CLog::Log(LOGDEBUG, "CDVDPlayerAudio::%s pll:%.4f (%.4f) proportional:%.4f integral:%.4f", __FUNCTION__, m_plladjust, new_adjust, proportional, m_integral);
++ double e = std::max(std::min(m_error, DVD_MSEC_TO_TIME(10)), -DVD_MSEC_TO_TIME(10));
++ m_plladjust = 1.0 + e * 1.5e-8;
++ m_last_plladjust = g_RBP.AdjustHDMIClock(m_plladjust);
++ CLog::Log(LOGDEBUG, "CDVDPlayerAudio::%s pll:%.5f (%.5f) error:%.6f e:%.6f", __FUNCTION__, m_plladjust, m_last_plladjust, m_error, e * 1.5e-8 );
+ #endif
+ }
++ m_last_error = m_error;
+ }
+ }
+
+diff --git a/xbmc/cores/dvdplayer/DVDPlayerAudio.h b/xbmc/cores/dvdplayer/DVDPlayerAudio.h
+index 02c64a0..37bf4bd 100644
+--- a/xbmc/cores/dvdplayer/DVDPlayerAudio.h
++++ b/xbmc/cores/dvdplayer/DVDPlayerAudio.h
+@@ -233,6 +233,8 @@ class CDVDPlayerAudio : public CThread, public IDVDStreamPlayerAudio
+ double m_maxspeedadjust;
+ double m_resampleratio; //resample ratio when using SYNC_RESAMPLE, used for the codec info
+ double m_plladjust; // for display using SYNC_PLLADJUST
++ double m_last_error; // for display using SYNC_PLLADJUST
++ double m_last_plladjust; // for display using SYNC_PLLADJUST
+
+ struct SInfo
+ {
+
+From 14568a4a6a45449d3929effd789f7073a92d28ce Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Sat, 15 Nov 2014 12:03:34 +0000
+Subject: [PATCH 45/61] [dvdplayer] Add lock for player creation
+
+---
+ xbmc/cores/dvdplayer/DVDPlayer.cpp | 3 +++
+ xbmc/cores/dvdplayer/DVDPlayer.h | 1 +
+ 2 files changed, 4 insertions(+)
+
+diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp
+index cb512ed..a27291b 100644
+--- a/xbmc/cores/dvdplayer/DVDPlayer.cpp
++++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp
+@@ -494,6 +494,7 @@ void CSelectionStreams::Update(CDVDInputStream* input, CDVDDemux* demuxer, std::
+
+ void CDVDPlayer::CreatePlayers()
+ {
++ CSingleLock lock(m_players_lock);
+ #ifdef HAS_OMXPLAYER
+ if (m_omxplayer_mode && OMXPlayerUnsuitable(m_HasVideo, m_HasAudio, m_pDemuxer, m_pInputStream, m_SelectionStreams))
+ {
+@@ -523,6 +524,7 @@ void CDVDPlayer::CreatePlayers()
+
+ void CDVDPlayer::DestroyPlayers()
+ {
++ CSingleLock lock(m_players_lock);
+ if (!m_players_created)
+ return;
+ delete m_dvdPlayerVideo;
+@@ -4015,6 +4017,7 @@ double CDVDPlayer::GetQueueTime()
+
+ void CDVDPlayer::GetVideoStreamInfo(SPlayerVideoStreamInfo &info)
+ {
++ CSingleLock lock(m_players_lock);
+ info.bitrate = m_dvdPlayerVideo->GetVideoBitrate();
+
+ std::string retVal;
+diff --git a/xbmc/cores/dvdplayer/DVDPlayer.h b/xbmc/cores/dvdplayer/DVDPlayer.h
+index ef64076..7ea6ea6 100644
+--- a/xbmc/cores/dvdplayer/DVDPlayer.h
++++ b/xbmc/cores/dvdplayer/DVDPlayer.h
+@@ -554,4 +554,5 @@ class CDVDPlayer : public IPlayer, public CThread, public IDVDPlayer
+ // omxplayer variables
+ struct SOmxPlayerState m_OmxPlayerState;
+ bool m_omxplayer_mode; // using omxplayer acceleration
++ CCriticalSection m_players_lock;
+ };
+
+From 2ac37fc94952151c5b1699152c46fae2c148631b Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Wed, 19 Nov 2014 13:29:43 +0000
+Subject: [PATCH 46/61] [dvdplayeraudio] Add advancedsetting for configuring
+ max pll adjustment
+
+---
+ xbmc/cores/dvdplayer/DVDPlayerAudio.cpp | 8 +++++---
+ xbmc/settings/AdvancedSettings.cpp | 2 ++
+ xbmc/settings/AdvancedSettings.h | 1 +
+ 3 files changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp
+index 4f25feb..3cfe8ad 100644
+--- a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp
++++ b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp
+@@ -25,6 +25,7 @@
+ #include "DVDCodecs/DVDCodecs.h"
+ #include "DVDCodecs/DVDFactoryCodec.h"
+ #include "settings/Settings.h"
++#include "settings/AdvancedSettings.h"
+ #include "video/VideoReferenceClock.h"
+ #include "utils/log.h"
+ #include "utils/TimeUtils.h"
+@@ -715,10 +716,11 @@ void CDVDPlayerAudio::HandleSyncError(double duration)
+ else if (m_synctype == SYNC_PLLADJUST)
+ {
+ #if defined(TARGET_RASPBERRY_PI)
+- double e = std::max(std::min(m_error, DVD_MSEC_TO_TIME(10)), -DVD_MSEC_TO_TIME(10));
+- m_plladjust = 1.0 + e * 1.5e-8;
++ double e = std::max(std::min(m_error / DVD_MSEC_TO_TIME(10), 1.0), -1.0);
++ double adjust = g_advancedSettings.m_maxPllAdjust * 1e-6;
++ m_plladjust = 1.0 + e * adjust;
+ m_last_plladjust = g_RBP.AdjustHDMIClock(m_plladjust);
+- CLog::Log(LOGDEBUG, "CDVDPlayerAudio::%s pll:%.5f (%.5f) error:%.6f e:%.6f", __FUNCTION__, m_plladjust, m_last_plladjust, m_error, e * 1.5e-8 );
++ CLog::Log(LOGDEBUG, "CDVDPlayerAudio::%s pll:%.5f (%.5f) error:%.6f e:%.6f a:%f", __FUNCTION__, m_plladjust, m_last_plladjust, m_error, e * adjust, adjust );
+ #endif
+ }
+ m_last_error = m_error;
+diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp
+index 69b7832..5eca79a 100644
+--- a/xbmc/settings/AdvancedSettings.cpp
++++ b/xbmc/settings/AdvancedSettings.cpp
+@@ -108,6 +108,7 @@ void CAdvancedSettings::Initialize()
+
+ m_audioHeadRoom = 0;
+ m_ac3Gain = 12.0f;
++ m_maxPllAdjust = 300;
+ m_audioApplyDrc = true;
+ m_dvdplayerIgnoreDTSinWAV = false;
+
+@@ -481,6 +482,7 @@ void CAdvancedSettings::ParseSettingsFile(const CStdString &file)
+ if (pElement)
+ {
+ XMLUtils::GetFloat(pElement, "ac3downmixgain", m_ac3Gain, -96.0f, 96.0f);
++ XMLUtils::GetInt(pElement, "maxplladjust", m_maxPllAdjust, 0, 1000000);
+ XMLUtils::GetInt(pElement, "headroom", m_audioHeadRoom, 0, 12);
+ XMLUtils::GetString(pElement, "defaultplayer", m_audioDefaultPlayer);
+ // 101 on purpose - can be used to never automark as watched
+diff --git a/xbmc/settings/AdvancedSettings.h b/xbmc/settings/AdvancedSettings.h
+index ca995e3..99ed121 100644
+--- a/xbmc/settings/AdvancedSettings.h
++++ b/xbmc/settings/AdvancedSettings.h
+@@ -137,6 +137,7 @@ class CAdvancedSettings : public ISettingCallback, public ISettingsHandler
+
+ int m_audioHeadRoom;
+ float m_ac3Gain;
++ int m_maxPllAdjust;
+ CStdString m_audioDefaultPlayer;
+ float m_audioPlayCountMinimumPercent;
+ bool m_dvdplayerIgnoreDTSinWAV;
+
+From 10475adc38c9035919030e6b17b9d60c2c5e9e25 Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Wed, 19 Nov 2014 17:35:44 +0000
+Subject: [PATCH 47/61] [mmalrender] Skip some log message in bypass mode
+
+---
+ xbmc/cores/VideoRenderers/MMALRenderer.cpp | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.cpp b/xbmc/cores/VideoRenderers/MMALRenderer.cpp
+index 03a05de..c0ff30d 100644
+--- a/xbmc/cores/VideoRenderers/MMALRenderer.cpp
++++ b/xbmc/cores/VideoRenderers/MMALRenderer.cpp
+@@ -298,6 +298,9 @@ int CMMALRenderer::GetImage(YV12Image *image, int source, bool readonly)
+
+ void CMMALRenderer::ReleaseBuffer(int idx)
+ {
++ if (!m_bConfigured || m_format == RENDER_FMT_BYPASS)
++ return;
++
+ #if defined(MMAL_DEBUG_VERBOSE)
+ CLog::Log(LOGDEBUG, "%s::%s - %d", CLASSNAME, __func__, idx);
+ #endif
+@@ -366,13 +369,13 @@ void CMMALRenderer::RenderUpdate(bool clear, DWORD flags, DWORD alpha)
+
+ void CMMALRenderer::FlipPage(int source)
+ {
++ if (!m_bConfigured || m_format == RENDER_FMT_BYPASS)
++ return;
++
+ #if defined(MMAL_DEBUG_VERBOSE)
+ CLog::Log(LOGDEBUG, "%s::%s - %d", CLASSNAME, __func__, source);
+ #endif
+
+- if (!m_bConfigured || m_format == RENDER_FMT_BYPASS)
+- return;
+-
+ YUVBUFFER *buffer = &m_buffers[source];
+ // we only want to upload frames once
+ if (buffer->flipindex++)
+
+From 030e02b42f71aac7efdf1c9e0554772503697e72 Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Mon, 24 Nov 2014 21:24:25 +0000
+Subject: [PATCH 48/61] [mmalcodec] Avoid deinterlace for dvd menus for now
+
+---
+ xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp
+index 6742e0e..a1f11e9 100644
+--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp
++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp
+@@ -883,7 +883,7 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts)
+
+ bool deinterlace = m_interlace_mode != MMAL_InterlaceProgressive;
+
+- if (deinterlace_request == VS_DEINTERLACEMODE_OFF)
++ if (m_hints.stills || deinterlace_request == VS_DEINTERLACEMODE_OFF)
+ deinterlace = false;
+ else if (deinterlace_request == VS_DEINTERLACEMODE_FORCE)
+ deinterlace = true;
+
+From c4d184e405053e45b8fdac3e80eafdc0409a8868 Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Mon, 24 Nov 2014 22:07:25 +0000
+Subject: [PATCH 49/61] [dvdplayervideo] Prod decoder when in stills mode
+
+An asynchronous hardware decoder doesn't only produce output pictures when new packets arrive.
+In dvd stills mode give it a chance to return pictures that weren't ready when frame was decoded.
+---
+ xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 46 ++++++++++++++++++++-------------
+ 1 file changed, 28 insertions(+), 18 deletions(-)
+
+diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
+index f030e37..7a8fc10 100644
+--- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
++++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
+@@ -324,7 +324,8 @@ void CDVDPlayerVideo::Process()
+
+ while (!m_bStop)
+ {
+- int iQueueTimeOut = (int)(m_stalled ? frametime / 4 : frametime * 10) / 1000;
++ bool bPictureWaiting = m_hints.stills && (m_pVideoCodec->Decode(NULL, 0, DVD_NOPTS_VALUE, DVD_NOPTS_VALUE) & VC_PICTURE);
++ int iQueueTimeOut = (int)(bPictureWaiting ? 0 : (m_hints.stills || m_stalled) ? frametime / 4 : frametime * 10) / 1000;
+ int iPriority = (m_speed == DVD_PLAYSPEED_PAUSE && m_started) ? 1 : 0;
+
+ CDVDMsg* pMsg;
+@@ -341,27 +342,36 @@ void CDVDPlayerVideo::Process()
+ if( iPriority )
+ continue;
+
+- //Okey, start rendering at stream fps now instead, we are likely in a stillframe
+- if( !m_stalled )
++ // check for picture waiting
++ if (bPictureWaiting)
+ {
+- if(m_started)
+- CLog::Log(LOGINFO, "CDVDPlayerVideo - Stillframe detected, switching to forced %f fps", m_fFrameRate);
+- m_stalled = true;
+- pts+= frametime*4;
++ // create a dummy demuxer packet to prod the decode logic
++ pMsg = new CDVDMsgDemuxerPacket(CDVDDemuxUtils::AllocateDemuxPacket(0), false);
+ }
+-
+- //Waiting timed out, output last picture
+- if( picture.iFlags & DVP_FLAG_ALLOCATED )
++ else
+ {
+- //Remove interlaced flag before outputting
+- //no need to output this as if it was interlaced
+- picture.iFlags &= ~DVP_FLAG_INTERLACED;
+- picture.iFlags |= DVP_FLAG_NOSKIP;
+- OutputPicture(&picture, pts);
+- pts+= frametime;
+- }
++ //Okey, start rendering at stream fps now instead, we are likely in a stillframe
++ if( !m_stalled )
++ {
++ if(m_started)
++ CLog::Log(LOGINFO, "CDVDPlayerVideo - Stillframe detected, switching to forced %f fps", m_fFrameRate);
++ m_stalled = true;
++ pts+= frametime*4;
++ }
+
+- continue;
++ //Waiting timed out, output last picture
++ if( picture.iFlags & DVP_FLAG_ALLOCATED )
++ {
++ //Remove interlaced flag before outputting
++ //no need to output this as if it was interlaced
++ picture.iFlags &= ~DVP_FLAG_INTERLACED;
++ picture.iFlags |= DVP_FLAG_NOSKIP;
++ OutputPicture(&picture, pts);
++ pts+= frametime;
++ }
++
++ continue;
++ }
+ }
+
+ if (pMsg->IsType(CDVDMsg::GENERAL_SYNCHRONIZE))
+
+From b3522aea35dd182a42979a3d3f98d847593bac54 Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Thu, 27 Nov 2014 16:20:56 +0000
+Subject: [PATCH 50/61] [mmalcodec] Skip some setup that is not required when
+ closing
+
+---
+ xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 27 ++++++++++++----------
+ 1 file changed, 15 insertions(+), 12 deletions(-)
+
+diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp
+index a1f11e9..a11fa65 100644
+--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp
++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp
+@@ -708,11 +708,11 @@ void CMMALVideo::Dispose()
+ {
+ // we are happy to exit, but let last shared pointer being deleted trigger the destructor
+ bool done = false;
++ m_finished = true;
+ Reset();
+ pthread_mutex_lock(&m_output_mutex);
+ if (!m_output_busy)
+ done = true;
+- m_finished = true;
+ pthread_mutex_unlock(&m_output_mutex);
+ if (g_advancedSettings.CanLogComponent(LOGVIDEO))
+ CLog::Log(LOGDEBUG, "%s::%s dts_queue(%d) ready_queue(%d) busy_queue(%d) done:%d", CLASSNAME, __func__, m_dts_queue.size(), m_output_ready.size(), m_output_busy, done);
+@@ -941,19 +941,21 @@ void CMMALVideo::Reset(void)
+ if (g_advancedSettings.CanLogComponent(LOGVIDEO))
+ CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__);
+
+- if (m_dec_input)
++ if (m_dec_input && m_dec_input->is_enabled)
+ mmal_port_disable(m_dec_input);
+- if (m_deint_connection)
++ if (m_deint_connection && m_deint_connection->is_enabled)
+ mmal_connection_disable(m_deint_connection);
+- if (m_dec_output)
++ if (m_dec_output && m_dec_output->is_enabled)
+ mmal_port_disable(m_dec_output);
+- if (m_dec_input)
+- mmal_port_enable(m_dec_input, dec_input_port_cb);
+- if (m_deint_connection)
+- mmal_connection_enable(m_deint_connection);
+- if (m_dec_output)
+- mmal_port_enable(m_dec_output, dec_output_port_cb_static);
+-
++ if (!m_finished)
++ {
++ if (m_dec_input)
++ mmal_port_enable(m_dec_input, dec_input_port_cb);
++ if (m_deint_connection)
++ mmal_connection_enable(m_deint_connection);
++ if (m_dec_output)
++ mmal_port_enable(m_dec_output, dec_output_port_cb_static);
++ }
+ // blow all ready video frames
+ bool old_drop_state = m_drop_state;
+ SetDropState(true);
+@@ -967,7 +969,8 @@ void CMMALVideo::Reset(void)
+ if (!old_drop_state)
+ SetDropState(false);
+
+- SendCodecConfigData();
++ if (!m_finished)
++ SendCodecConfigData();
+
+ m_startframe = false;
+ m_decoderPts = DVD_NOPTS_VALUE;
+
+From 98aee3513b7caf14a6bba2e465f28edec5b19837 Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Thu, 27 Nov 2014 16:31:56 +0000
+Subject: [PATCH 51/61] [languageinvoker] Reduce priority of python threads
+
+---
+ xbmc/interfaces/generic/LanguageInvokerThread.cpp | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/xbmc/interfaces/generic/LanguageInvokerThread.cpp b/xbmc/interfaces/generic/LanguageInvokerThread.cpp
+index 7b0d903..f92aa3e 100644
+--- a/xbmc/interfaces/generic/LanguageInvokerThread.cpp
++++ b/xbmc/interfaces/generic/LanguageInvokerThread.cpp
+@@ -51,6 +51,11 @@ bool CLanguageInvokerThread::execute(const std::string &script, const std::vecto
+ m_args = arguments;
+
+ Create();
++ #ifdef TARGET_RASPBERRY_PI
++ /* low prio */
++ SetPriority(GetPriority()-1);
++ #endif
++
+ return true;
+ }
+
+
+From bad28af8f1636a612acc0ccc5ec9e43b67abce75 Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Thu, 27 Nov 2014 17:53:46 +0000
+Subject: [PATCH 52/61] [mmalcodec] Try reducing number of video frames
+
+---
+ xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 2 +-
+ xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp
+index a11fa65..dd08c95 100644
+--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp
++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp
+@@ -628,7 +628,7 @@ bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, MMALVide
+ if (status != MMAL_SUCCESS)
+ CLog::Log(LOGERROR, "%s::%s Failed to disable error concealment on %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status));
+
+- status = mmal_port_parameter_set_uint32(m_dec_input, MMAL_PARAMETER_EXTRA_BUFFERS, NUM_BUFFERS);
++ status = mmal_port_parameter_set_uint32(m_dec_input, MMAL_PARAMETER_EXTRA_BUFFERS, GetAllowedReferences());
+ if (status != MMAL_SUCCESS)
+ CLog::Log(LOGERROR, "%s::%s Failed to enable extra buffers on %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status));
+
+diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h
+index 4f81bbd..79a4bfd 100644
+--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h
++++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h
+@@ -86,7 +86,7 @@ class CMMALVideo
+ virtual void Reset(void);
+ virtual bool GetPicture(DVDVideoPicture *pDvdVideoPicture);
+ virtual bool ClearPicture(DVDVideoPicture* pDvdVideoPicture);
+- virtual unsigned GetAllowedReferences() { return NUM_BUFFERS; }
++ virtual unsigned GetAllowedReferences() { return 3; }
+ virtual void SetDropState(bool bDrop);
+ virtual const char* GetName(void) { return (const char*)m_pFormatName; }
+ virtual bool GetCodecStats(double &pts, int &droppedPics);
+
+From 1b411d8f41b1c8d8d49b950e032fb78cb2b34122 Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Mon, 1 Dec 2014 17:31:00 +0000
+Subject: [PATCH 53/61] [mmalcodec] Ensure we have requested number of buffers
+ in non-accelerated case
+
+---
+ xbmc/cores/VideoRenderers/MMALRenderer.cpp | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.cpp b/xbmc/cores/VideoRenderers/MMALRenderer.cpp
+index c0ff30d..6d461bd 100644
+--- a/xbmc/cores/VideoRenderers/MMALRenderer.cpp
++++ b/xbmc/cores/VideoRenderers/MMALRenderer.cpp
+@@ -100,7 +100,7 @@ bool CMMALRenderer::init_vout(MMAL_ES_FORMAT_T *format)
+ return false;
+ }
+
+- m_vout_input->buffer_num = m_vout_input->buffer_num_recommended;
++ m_vout_input->buffer_num = std::max(m_vout_input->buffer_num_recommended, (uint32_t)m_NumYV12Buffers);
+ m_vout_input->buffer_size = m_vout_input->buffer_size_recommended;
+
+ status = mmal_port_enable(m_vout_input, vout_input_port_cb_static);
+
+From fb6f3b4ead397628ec80a4cc37e0f03adc76eeaa Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Wed, 3 Dec 2014 21:17:53 +0000
+Subject: [PATCH 54/61] [omxplayer] Add some info about hdmi sync to codec
+ overlay
+
+---
+ xbmc/cores/omxplayer/OMXPlayerVideo.cpp | 8 +++++++-
+ xbmc/cores/omxplayer/OMXVideo.cpp | 24 ++++++++++++++++++++++++
+ xbmc/cores/omxplayer/OMXVideo.h | 1 +
+ 3 files changed, 32 insertions(+), 1 deletion(-)
+
+diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
+index 605318c9..77b9461 100644
+--- a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
++++ b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
+@@ -618,12 +618,18 @@ void OMXPlayerVideo::SetSpeed(int speed)
+
+ std::string OMXPlayerVideo::GetPlayerInfo()
+ {
++ double match = 0.0f, phase = 0.0f, pll = 0.0f;
+ std::ostringstream s;
+ s << "fr:" << fixed << setprecision(3) << m_fFrameRate;
+ s << ", vq:" << setw(2) << min(99,GetLevel()) << "%";
+ s << ", dc:" << m_codecname;
+ s << ", Mb/s:" << fixed << setprecision(2) << (double)GetVideoBitrate() / (1024.0*1024.0);
+-
++ if (m_omxVideo.GetPlayerInfo(match, phase, pll))
++ {
++ s << ", match:" << fixed << setprecision(2) << match;
++ s << ", phase:" << fixed << setprecision(2) << phase;
++ s << ", pll:" << fixed << setprecision(5) << pll;
++ }
+ return s.str();
+ }
+
+diff --git a/xbmc/cores/omxplayer/OMXVideo.cpp b/xbmc/cores/omxplayer/OMXVideo.cpp
+index 99bb7eb..dea0e11 100644
+--- a/xbmc/cores/omxplayer/OMXVideo.cpp
++++ b/xbmc/cores/omxplayer/OMXVideo.cpp
+@@ -759,6 +759,30 @@ unsigned int COMXVideo::GetSize()
+ return m_omx_decoder.GetInputBufferSize();
+ }
+
++bool COMXVideo::GetPlayerInfo(double &match, double &phase, double &pll)
++{
++ CSingleLock lock (m_critSection);
++ OMX_ERRORTYPE omx_err;
++ OMX_CONFIG_BRCMRENDERSTATSTYPE renderstats;
++
++ if (!m_hdmi_clock_sync || !m_omx_render.IsInitialized())
++ return false;
++ OMX_INIT_STRUCTURE(renderstats);
++ renderstats.nPortIndex = m_omx_render.GetInputPort();
++
++ omx_err = m_omx_render.GetParameter(OMX_IndexConfigBrcmRenderStats, &renderstats);
++ if(omx_err != OMX_ErrorNone)
++ {
++ CLog::Log(LOGERROR, "COMXVideo::GetPlayerInfo error GetParameter OMX_IndexParamPortDefinition omx_err(0x%08x)\n", omx_err);
++ return false;
++ }
++ match = renderstats.nMatch * 1e-6;
++ phase = (double)renderstats.nPhase / (double)renderstats.nPeriod;
++ pll = (double)renderstats.nPixelClock / (double)renderstats.nPixelClockNominal;
++ return true;
++}
++
++
+ int COMXVideo::Decode(uint8_t *pData, int iSize, double pts)
+ {
+ CSingleLock lock (m_critSection);
+diff --git a/xbmc/cores/omxplayer/OMXVideo.h b/xbmc/cores/omxplayer/OMXVideo.h
+index c8fd5fb..9f26427 100644
+--- a/xbmc/cores/omxplayer/OMXVideo.h
++++ b/xbmc/cores/omxplayer/OMXVideo.h
+@@ -61,6 +61,7 @@ class COMXVideo
+ std::string GetDecoderName() { return m_video_codec_name; };
+ void SetVideoRect(const CRect& SrcRect, const CRect& DestRect, RENDER_STEREO_MODE video_mode, RENDER_STEREO_MODE display_mode);
+ int GetInputBufferSize();
++ bool GetPlayerInfo(double &match, double &phase, double &pll);
+ void SubmitEOS();
+ bool IsEOS();
+ bool SubmittedEOS() const { return m_submitted_eos; }
+
+From 6fb024728dc90801ca8e77687658c8deb2b418b8 Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Sun, 7 Dec 2014 15:21:18 +0000
+Subject: [PATCH 55/61] [omxplayer] Remove test of removed setting, avoids a
+ log message
+
+---
+ xbmc/cores/omxplayer/OMXPlayerAudio.cpp | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/xbmc/cores/omxplayer/OMXPlayerAudio.cpp b/xbmc/cores/omxplayer/OMXPlayerAudio.cpp
+index 66014d4..c2da2d2 100644
+--- a/xbmc/cores/omxplayer/OMXPlayerAudio.cpp
++++ b/xbmc/cores/omxplayer/OMXPlayerAudio.cpp
+@@ -525,17 +525,17 @@ AEDataFormat OMXPlayerAudio::GetDataFormat(CDVDStreamInfo hints)
+ /* check our audio capabilties */
+
+ /* pathrought is overriding hw decode*/
+- if(hints.codec == AV_CODEC_ID_AC3 && CAEFactory::SupportsRaw(AE_FMT_AC3, hints.samplerate) && !CSettings::Get().GetBool("audiooutput.dualaudio"))
++ if(hints.codec == AV_CODEC_ID_AC3 && CAEFactory::SupportsRaw(AE_FMT_AC3, hints.samplerate))
+ {
+ dataFormat = AE_FMT_AC3;
+ m_passthrough = true;
+ }
+- if(hints.codec == AV_CODEC_ID_EAC3 && CAEFactory::SupportsRaw(AE_FMT_AC3, hints.samplerate * 4) && !CSettings::Get().GetBool("audiooutput.dualaudio"))
++ if(hints.codec == AV_CODEC_ID_EAC3 && CAEFactory::SupportsRaw(AE_FMT_AC3, hints.samplerate * 4))
+ {
+ dataFormat = AE_FMT_EAC3;
+ m_passthrough = true;
+ }
+- if(hints.codec == AV_CODEC_ID_DTS && CAEFactory::SupportsRaw(AE_FMT_DTS, hints.samplerate) && !CSettings::Get().GetBool("audiooutput.dualaudio"))
++ if(hints.codec == AV_CODEC_ID_DTS && CAEFactory::SupportsRaw(AE_FMT_DTS, hints.samplerate))
+ {
+ dataFormat = AE_FMT_DTS;
+ m_passthrough = true;
+
+From fe843625b9ad099a11ba8381a8ed9de8bcffec1c Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Sun, 28 Dec 2014 19:13:51 +0000
+Subject: [PATCH 56/61] [omxplayer] Skip packet concatenation for WMAV2 files
+
+See: http://forum.kodi.tv/showthread.php?tid=212552
+---
+ xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp b/xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp
+index 94b673e..1a920f7 100644
+--- a/xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp
++++ b/xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp
+@@ -97,8 +97,8 @@ bool COMXAudioCodecOMX::Open(CDVDStreamInfo &hints)
+ if (m_pCodecContext->request_channel_layout)
+ CLog::Log(LOGNOTICE,"COMXAudioCodecOMX::Open() Requesting channel layout of %x", (unsigned)m_pCodecContext->request_channel_layout);
+
+- // vorbis has variable sized planar output, so skip concatenation
+- if (hints.codec == AV_CODEC_ID_VORBIS)
++ // vorbis and wma2v2 have variable sized planar output, so skip concatenation
++ if (hints.codec == AV_CODEC_ID_VORBIS || hints.codec == AV_CODEC_ID_WMAV2)
+ m_bNoConcatenate = true;
+
+ if(m_pCodecContext->bits_per_coded_sample == 0)
+
+From 1a6ebaab8be9dcc9ae335121189b5f3bf2d19f8a Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Wed, 31 Dec 2014 17:08:52 +0000
+Subject: [PATCH 57/61] filesystem: Make browsing into archives enbabled by
+ default on Pi
+
+This causes issues for people who scan library with archives disabled, then subsequently enable it.
+The library has the .rar files in which don't play without removing and re-adding.
+
+We'll let people who don't use archives disable it manually
+---
+ system/settings/rbp.xml | 10 ----------
+ 1 file changed, 10 deletions(-)
+
+diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml
+index 4c2ef41..3260465 100644
+--- a/system/settings/rbp.xml
++++ b/system/settings/rbp.xml
+@@ -1,15 +1,5 @@
+
+
+-
+-
+-
+-
+- false
+-
+-
+-
+-
+-
+
+
+
+
+From 32b9d35387473c681e524db4c6e82173d498eb40 Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Wed, 31 Dec 2014 16:03:32 +0000
+Subject: [PATCH 58/61] [PVR] Fix for slow metadata updates of recordings
+
+See: http://forum.kodi.tv/showthread.php?tid=210774
+
+metaron identified that entering the recordings screen wih 850 recordings on a Pi
+was taking about 40 seconds. The database is opened and closed for every recording,
+and this dominates the time taken. With the database open/close pulled out of the loop
+it now takes 1.4 seconds.
+
+squash: Changes suggested by Jalle19
+---
+ xbmc/pvr/recordings/PVRRecording.cpp | 20 +++++++-------------
+ xbmc/pvr/recordings/PVRRecording.h | 4 +++-
+ xbmc/pvr/recordings/PVRRecordings.cpp | 27 +++++++++++++++++----------
+ xbmc/pvr/recordings/PVRRecordings.h | 4 +++-
+ 4 files changed, 30 insertions(+), 25 deletions(-)
+
+diff --git a/xbmc/pvr/recordings/PVRRecording.cpp b/xbmc/pvr/recordings/PVRRecording.cpp
+index ccf2693..905f42c 100644
+--- a/xbmc/pvr/recordings/PVRRecording.cpp
++++ b/xbmc/pvr/recordings/PVRRecording.cpp
+@@ -221,7 +221,7 @@ bool CPVRRecording::SetPlayCount(int count)
+ return true;
+ }
+
+-void CPVRRecording::UpdateMetadata(void)
++void CPVRRecording::UpdateMetadata(CVideoDatabase &db)
+ {
+ if (m_bGotMetaData)
+ return;
+@@ -231,20 +231,14 @@ void CPVRRecording::UpdateMetadata(void)
+
+ if (!supportsPlayCount || !supportsLastPlayed)
+ {
+- CVideoDatabase db;
+- if (db.Open())
++ if (!supportsPlayCount)
+ {
+- if (!supportsPlayCount)
+- {
+- CFileItem pFileItem(*this);
+- m_playCount = db.GetPlayCount(pFileItem);
+- }
+-
+- if (!supportsLastPlayed)
+- db.GetResumeBookMark(m_strFileNameAndPath, m_resumePoint);
+-
+- db.Close();
++ CFileItem pFileItem(*this);
++ m_playCount = db.GetPlayCount(pFileItem);
+ }
++
++ if (!supportsLastPlayed)
++ db.GetResumeBookMark(m_strFileNameAndPath, m_resumePoint);
+ }
+
+ m_bGotMetaData = true;
+diff --git a/xbmc/pvr/recordings/PVRRecording.h b/xbmc/pvr/recordings/PVRRecording.h
+index 91af28a..c9d9359 100644
+--- a/xbmc/pvr/recordings/PVRRecording.h
++++ b/xbmc/pvr/recordings/PVRRecording.h
+@@ -39,6 +39,8 @@
+ #include "video/VideoInfoTag.h"
+ #include "XBDateTime.h"
+
++class CVideoDatabase;
++
+ namespace PVR
+ {
+ class CPVRRecording;
+@@ -149,7 +151,7 @@ namespace PVR
+ * @brief Get the resume point and play count from the database if the
+ * client doesn't handle it itself.
+ */
+- void UpdateMetadata(void);
++ void UpdateMetadata(CVideoDatabase &db);
+
+ /*!
+ * @brief Update this tag with the contents of the given tag.
+diff --git a/xbmc/pvr/recordings/PVRRecordings.cpp b/xbmc/pvr/recordings/PVRRecordings.cpp
+index 34ef40f..7741efc 100644
+--- a/xbmc/pvr/recordings/PVRRecordings.cpp
++++ b/xbmc/pvr/recordings/PVRRecordings.cpp
+@@ -43,7 +43,14 @@ CPVRRecordings::CPVRRecordings(void) :
+ m_iLastId(0),
+ m_bGroupItems(true)
+ {
++ m_database.Open();
++}
+
++CPVRRecordings::~CPVRRecordings()
++{
++ Clear();
++ if (m_database.IsOpen())
++ m_database.Close();
+ }
+
+ void CPVRRecordings::UpdateFromClients(void)
+@@ -119,8 +126,9 @@ void CPVRRecordings::GetSubDirectories(const std::string &strBase, CFileItemList
+ strFilePath = StringUtils::Format("pvr://recordings/%s/%s/", strUseBase.c_str(), strCurrent.c_str());
+
+ CFileItemPtr pFileItem;
+- current->UpdateMetadata();
+-
++ if (m_database.IsOpen())
++ current->UpdateMetadata(m_database);
++
+ if (!results->Contains(strFilePath))
+ {
+ pFileItem.reset(new CFileItem(strCurrent, true));
+@@ -250,8 +258,7 @@ bool CPVRRecordings::SetRecordingsPlayCount(const CFileItemPtr &item, int count)
+ {
+ bool bResult = false;
+
+- CVideoDatabase database;
+- if (database.Open())
++ if (m_database.IsOpen())
+ {
+ bResult = true;
+
+@@ -291,15 +298,13 @@ bool CPVRRecordings::SetRecordingsPlayCount(const CFileItemPtr &item, int count)
+ // Clear resume bookmark
+ if (count > 0)
+ {
+- database.ClearBookMarksOfFile(pItem->GetPath(), CBookmark::RESUME);
++ m_database.ClearBookMarksOfFile(pItem->GetPath(), CBookmark::RESUME);
+ recording->SetLastPlayedPosition(0);
+ }
+
+- database.SetPlayCount(*pItem, count);
++ m_database.SetPlayCount(*pItem, count);
+ }
+ }
+-
+- database.Close();
+ }
+
+ return bResult;
+@@ -330,7 +335,8 @@ bool CPVRRecordings::GetDirectory(const std::string& strPath, CFileItemList &ite
+ if (!IsDirectoryMember(strDirectoryPath, current->m_strDirectory))
+ continue;
+
+- current->UpdateMetadata();
++ if (m_database.IsOpen())
++ current->UpdateMetadata(m_database);
+ CFileItemPtr pFileItem(new CFileItem(*current));
+ pFileItem->SetLabel2(current->RecordingTimeAsLocalTime().GetAsLocalizedDateTime(true, false));
+ pFileItem->m_dateTime = current->RecordingTimeAsLocalTime();
+@@ -369,7 +375,8 @@ void CPVRRecordings::GetAll(CFileItemList &items)
+ for (PVR_RECORDINGMAP_CITR it = m_recordings.begin(); it != m_recordings.end(); it++)
+ {
+ CPVRRecordingPtr current = it->second;
+- current->UpdateMetadata();
++ if (m_database.IsOpen())
++ current->UpdateMetadata(m_database);
+
+ CFileItemPtr pFileItem(new CFileItem(*current));
+ pFileItem->SetLabel2(current->RecordingTimeAsLocalTime().GetAsLocalizedDateTime(true, false));
+diff --git a/xbmc/pvr/recordings/PVRRecordings.h b/xbmc/pvr/recordings/PVRRecordings.h
+index 6b8cb14..2bcc834 100644
+--- a/xbmc/pvr/recordings/PVRRecordings.h
++++ b/xbmc/pvr/recordings/PVRRecordings.h
+@@ -24,6 +24,7 @@
+ #include "threads/Thread.h"
+ #include "utils/Observer.h"
+ #include "video/VideoThumbLoader.h"
++#include "video/VideoDatabase.h"
+
+ #define PVR_ALL_RECORDINGS_PATH_EXTENSION "-1"
+
+@@ -40,6 +41,7 @@ namespace PVR
+ PVR_RECORDINGMAP m_recordings;
+ unsigned int m_iLastId;
+ bool m_bGroupItems;
++ CVideoDatabase m_database;
+
+ virtual void UpdateFromClients(void);
+ virtual std::string TrimSlashes(const std::string &strOrig) const;
+@@ -58,7 +60,7 @@ namespace PVR
+
+ public:
+ CPVRRecordings(void);
+- virtual ~CPVRRecordings(void) { Clear(); };
++ virtual ~CPVRRecordings(void);
+
+ int Load();
+ void Unload();
+
+From deb907165630c7c6bb61f81a005eee94c964105e Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Mon, 29 Dec 2014 17:20:00 +0000
+Subject: [PATCH 59/61] [dvdplayer] Allow pll adjustment to go higher, but tail
+ off more gradually
+
+---
+ xbmc/cores/dvdplayer/DVDPlayerAudio.cpp | 2 +-
+ xbmc/settings/AdvancedSettings.cpp | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp
+index 3cfe8ad..5db48a8 100644
+--- a/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp
++++ b/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp
+@@ -716,7 +716,7 @@ void CDVDPlayerAudio::HandleSyncError(double duration)
+ else if (m_synctype == SYNC_PLLADJUST)
+ {
+ #if defined(TARGET_RASPBERRY_PI)
+- double e = std::max(std::min(m_error / DVD_MSEC_TO_TIME(10), 1.0), -1.0);
++ double e = std::max(std::min(m_error / DVD_MSEC_TO_TIME(50), 1.0), -1.0);
+ double adjust = g_advancedSettings.m_maxPllAdjust * 1e-6;
+ m_plladjust = 1.0 + e * adjust;
+ m_last_plladjust = g_RBP.AdjustHDMIClock(m_plladjust);
+diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp
+index 5eca79a..b1e396a 100644
+--- a/xbmc/settings/AdvancedSettings.cpp
++++ b/xbmc/settings/AdvancedSettings.cpp
+@@ -108,7 +108,7 @@ void CAdvancedSettings::Initialize()
+
+ m_audioHeadRoom = 0;
+ m_ac3Gain = 12.0f;
+- m_maxPllAdjust = 300;
++ m_maxPllAdjust = 1000;
+ m_audioApplyDrc = true;
+ m_dvdplayerIgnoreDTSinWAV = false;
+
+
+From 9c137af65807edcfa0e3e9910a1ae8689be7ccae Mon Sep 17 00:00:00 2001
+From: popcornmix
+Date: Thu, 11 Dec 2014 17:00:57 +0000
+Subject: [PATCH 60/61] Fix for UI not showing both extractflags and
+ extractthumb
+
+---
+ language/English/strings.po | 11 ++++++++---
+ system/settings/settings.xml | 10 +++++-----
+ 2 files changed, 13 insertions(+), 8 deletions(-)
+
+diff --git a/language/English/strings.po b/language/English/strings.po
+index 24f9636..c54cb25 100755
+--- a/language/English/strings.po
++++ b/language/English/strings.po
+@@ -10790,7 +10790,7 @@ msgstr ""
+
+ #: system/settings/settings.xml
+ msgctxt "#20433"
+-msgid "Extract thumbnails and video information"
++msgid "Extract video information from files"
+ msgstr ""
+
+ #: xbmc/dialogs/GUIDialogSmartPlaylistRule.cpp
+@@ -14164,7 +14164,7 @@ msgstr ""
+ #. Description of setting "Videos -> File lists -> Extract thumbnails and video information" with label #20433
+ #: system/settings/settings.xml
+ msgctxt "#36178"
+-msgid "Extract thumbnails and metadata information such as codec and aspect ratio from videos."
++msgid "Extract metadata information such as codec and aspect ratio from videos."
+ msgstr ""
+
+ #. Description of setting "Videos -> File lists -> Replace file names with library titles" with label #20419
+@@ -14176,7 +14176,7 @@ msgstr ""
+ #. Description of setting "Videos -> File lists -> Extract thumbnails and video information" with label #20433
+ #: system/settings/settings.xml
+ msgctxt "#36180"
+-msgid "Extract thumbnails and information, such as codecs and aspect ratio, to display in Library Mode."
++msgid "Extract thumbnails, to display in Library Mode."
+ msgstr ""
+
+ #: system/settings/settings.xml
+@@ -16172,3 +16172,8 @@ msgstr ""
+ msgctxt "#38009"
+ msgid "%i dB"
+ msgstr ""
++
++#: system/settings/settings.xml
++msgctxt "#38015"
++msgid "Extract thumbnails from video files"
++msgstr ""
+diff --git a/system/settings/settings.xml b/system/settings/settings.xml
+index dbddcb6..756475f 100644
+--- a/system/settings/settings.xml
++++ b/system/settings/settings.xml
+@@ -802,17 +802,17 @@
+
+
+
+-
+- 1
++
+-