diff --git a/build/make/configure.sh b/build/make/configure.sh index 552f8c188695e9a5fdc03d3b6c231e554c66dc5e..be34778233c2f31740595c3d6ece810ad1073edb 100755 --- a/build/make/configure.sh +++ b/build/make/configure.sh @@ -389,6 +389,7 @@ LDFLAGS = ${LDFLAGS} ASFLAGS = ${ASFLAGS} extralibs = ${extralibs} AS_SFX = ${AS_SFX:-.asm} +RTCD_OPTIONS = ${RTCD_OPTIONS} EOF if enabled rvct; then cat >> $1 << EOF @@ -451,8 +452,20 @@ process_common_cmdline() { ;; --enable-?*|--disable-?*) eval `echo "$opt" | sed 's/--/action=/;s/-/ option=/;s/-/_/g'` - echo "${CMDLINE_SELECT} ${ARCH_EXT_LIST}" | grep "^ *$option\$" >/dev/null || die_unknown $opt - $action $option + if echo "${ARCH_EXT_LIST}" | grep "^ *$option\$" >/dev/null; then + [ $action = "disable" ] && RTCD_OPTIONS="${RTCD_OPTIONS}${opt} " + else + echo "${CMDLINE_SELECT}" | grep "^ *$option\$" >/dev/null || + die_unknown $opt + fi $action $option + ;; + --require-?*) + eval `echo "$opt" | sed 's/--/action=/;s/-/ option=/;s/-/_/g'` + if echo "${ARCH_EXT_LIST}" none | grep "^ *$option\$" >/dev/null; then + RTCD_OPTIONS="${RTCD_OPTIONS}${opt} " + else + die_unknown $opt + fi ;; --force-enable-?*|--force-disable-?*) eval `echo "$opt" | sed 's/--force-/action=/;s/-/ option=/;s/-/_/g'` diff --git a/build/make/rtcd.sh b/build/make/rtcd.sh new file mode 100755 index 0000000000000000000000000000000000000000..ddf9e09a4e9674db91cbc79381691a1d7eada0c3 --- /dev/null +++ b/build/make/rtcd.sh @@ -0,0 +1,356 @@ +#!/bin/sh +self=$0 + +usage() { + cat <<EOF >&2 +Usage: $self [options] FILE + +Reads the Run Time CPU Detections definitions from FILE and generates a +C header file on stdout. + +Options: + --arch=ARCH Architecture to generate defs for (required) + --disable-EXT Disable support for EXT extensions + --require-EXT Require support for EXT extensions + --sym=SYMBOL Unique symbol to use for RTCD initialization function + --config=FILE File with CONFIG_FOO=yes lines to parse +EOF + exit 1 +} + +die() { + echo "$@" >&2 + exit 1 +} + +die_argument_required() { + die "Option $opt requires argument" +} + +for opt; do + optval="${opt#*=}" + case "$opt" in + --arch) die_argument_required;; + --arch=*) arch=${optval};; + --disable-*) eval "disable_${opt#--disable-}=true";; + --require-*) REQUIRES="${REQUIRES}${opt#--require-} ";; + --sym) die_argument_required;; + --sym=*) symbol=${optval};; + --config=*) config_file=${optval};; + -h|--help) + usage + ;; + -*) + die "Unrecognized option: ${opt%%=*}" + ;; + *) + defs_file="$defs_file $opt" + ;; + esac + shift +done +for f in $defs_file; do [ -f "$f" ] || usage; done +[ -n "$arch" ] || usage + +# Import the configuration +[ -f "$config_file" ] && eval $(grep CONFIG_ "$config_file") + +# +# Routines for the RTCD DSL to call +# +prototype() { + local rtyp + case "$1" in + unsigned) rtyp="$1 "; shift;; + esac + rtyp="${rtyp}$1" + local fn="$2" + local args="$3" + + eval "${2}_rtyp='$rtyp'" + eval "${2}_args='$3'" + ALL_FUNCS="$ALL_FUNCS $fn" + specialize $fn c +} + +specialize() { + local fn="$1" + shift + for opt in "$@"; do + eval "${fn}_${opt}=${fn}_${opt}" + done +} + +require() { + for fn in $ALL_FUNCS; do + for opt in "$@"; do + local ofn=$(eval "echo \$${fn}_${opt}") + [ -z "$ofn" ] && continue + + # if we already have a default, then we can disable it, as we know + # we can do better. + local best=$(eval "echo \$${fn}_default") + local best_ofn=$(eval "echo \$${best}") + [ -n "$best" ] && [ "$best_ofn" != "$ofn" ] && eval "${best}_link=false" + eval "${fn}_default=${fn}_${opt}" + eval "${fn}_${opt}_link=true" + done + done +} + +forward_decls() { + ALL_FORWARD_DECLS="$ALL_FORWARD_DECLS $1" +} + +# +# Include the user's directives +# +for f in $defs_file; do + . $f +done + +# +# Process the directives according to the command line +# +process_forward_decls() { + for fn in $ALL_FORWARD_DECLS; do + eval $fn + done +} + +determine_indirection() { + [ "$CONFIG_RUNTIME_CPU_DETECT" = "yes" ] || require $ALL_ARCHS + for fn in $ALL_FUNCS; do + local n="" + local rtyp="$(eval "echo \$${fn}_rtyp")" + local args="$(eval "echo \"\$${fn}_args\"")" + local dfn="$(eval "echo \$${fn}_default")" + dfn=$(eval "echo \$${dfn}") + for opt in "$@"; do + local ofn=$(eval "echo \$${fn}_${opt}") + [ -z "$ofn" ] && continue + local link=$(eval "echo \$${fn}_${opt}_link") + [ "$link" = "false" ] && continue + n="${n}x" + done + if [ "$n" = "x" ]; then + eval "${fn}_indirect=false" + else + eval "${fn}_indirect=true" + fi + done +} + +declare_function_pointers() { + for fn in $ALL_FUNCS; do + local rtyp="$(eval "echo \$${fn}_rtyp")" + local args="$(eval "echo \"\$${fn}_args\"")" + local dfn="$(eval "echo \$${fn}_default")" + dfn=$(eval "echo \$${dfn}") + for opt in "$@"; do + local ofn=$(eval "echo \$${fn}_${opt}") + [ -z "$ofn" ] && continue + echo "$rtyp ${ofn}($args);" + done + if [ "$(eval "echo \$${fn}_indirect")" = "false" ]; then + echo "#define ${fn} ${dfn}" + else + echo "RTCD_EXTERN $rtyp (*${fn})($args);" + fi + echo + done +} + +set_function_pointers() { + for fn in $ALL_FUNCS; do + local n="" + local rtyp="$(eval "echo \$${fn}_rtyp")" + local args="$(eval "echo \"\$${fn}_args\"")" + local dfn="$(eval "echo \$${fn}_default")" + dfn=$(eval "echo \$${dfn}") + if $(eval "echo \$${fn}_indirect"); then + echo " $fn = $dfn;" + for opt in "$@"; do + local ofn=$(eval "echo \$${fn}_${opt}") + [ -z "$ofn" ] && continue + [ "$ofn" = "$dfn" ] && continue; + local link=$(eval "echo \$${fn}_${opt}_link") + [ "$link" = "false" ] && continue + local cond="$(eval "echo \$have_${opt}")" + echo " if (${cond}) $fn = $ofn;" + done + fi + echo + done +} + +filter() { + local filtered + for opt in "$@"; do + [ -z $(eval "echo \$disable_${opt}") ] && filtered="$filtered $opt" + done + echo $filtered +} + +# +# Helper functions for generating the arch specific RTCD files +# +common_top() { + local outfile_basename=$(basename ${symbol:-rtcd.h}) + local include_guard=$(echo $outfile_basename | tr '[a-z]' '[A-Z]' | tr -c '[A-Z]' _) + cat <<EOF +#ifndef ${include_guard} +#define ${include_guard} + +#ifdef RTCD_C +#define RTCD_EXTERN +#else +#define RTCD_EXTERN extern +#endif + +$(process_forward_decls) + +$(declare_function_pointers c $ALL_ARCHS) + +void ${symbol:-rtcd}(void); +EOF +} + +common_bottom() { + cat <<EOF +#endif +EOF +} + +x86() { + determine_indirection c $ALL_ARCHS + + # Assign the helper variable for each enabled extension + for opt in $ALL_ARCHS; do + local uc=$(echo $opt | tr '[a-z]' '[A-Z]') + eval "have_${opt}=\"flags & HAS_${uc}\"" + done + + cat <<EOF +$(common_top) + +#ifdef RTCD_C +#include "vpx_ports/x86.h" +static void setup_rtcd_internal(void) +{ + int flags = x86_simd_caps(); + + (void)flags; + +$(set_function_pointers c $ALL_ARCHS) +} +#endif +$(common_bottom) +EOF +} + +arm() { + determine_indirection c $ALL_ARCHS + + # Assign the helper variable for each enabled extension + for opt in $ALL_ARCHS; do + local uc=$(echo $opt | tr '[a-z]' '[A-Z]') + eval "have_${opt}=\"flags & HAS_${uc}\"" + done + + cat <<EOF +$(common_top) +#include "vpx_config.h" + +#ifdef RTCD_C +#include "vpx_ports/arm.h" +static void setup_rtcd_internal(void) +{ + int flags = arm_cpu_caps(); + + (void)flags; + +$(set_function_pointers c $ALL_ARCHS) +} +#endif +$(common_bottom) +EOF +} + + +mips() { + determine_indirection c $ALL_ARCHS + cat <<EOF +$(common_top) +#include "vpx_config.h" + +#ifdef RTCD_C +static void setup_rtcd_internal(void) +{ +$(set_function_pointers c $ALL_ARCHS) +#if HAVE_DSPR2 +void dsputil_static_init(); +dsputil_static_init(); +#endif +} +#endif +$(common_bottom) +EOF +} + +unoptimized() { + determine_indirection c + cat <<EOF +$(common_top) +#include "vpx_config.h" + +#ifdef RTCD_C +static void setup_rtcd_internal(void) +{ +$(set_function_pointers c) +} +#endif +$(common_bottom) +EOF + +} +# +# Main Driver +# +require c +case $arch in + x86) + ALL_ARCHS=$(filter mmx sse sse2 sse3 ssse3 sse4_1) + x86 + ;; + x86_64) + ALL_ARCHS=$(filter mmx sse sse2 sse3 ssse3 sse4_1) + REQUIRES=${REQUIRES:-mmx sse sse2} + require $(filter $REQUIRES) + x86 + ;; + mips32) + ALL_ARCHS=$(filter mips32) + dspr2=$([ -f "$config_file" ] && eval echo $(grep HAVE_DSPR2 "$config_file")) + HAVE_DSPR2="${dspr2#*=}" + if [ "$HAVE_DSPR2" = "yes" ]; then + ALL_ARCHS=$(filter mips32 dspr2) + fi + mips + ;; + armv5te) + ALL_ARCHS=$(filter edsp) + arm + ;; + armv6) + ALL_ARCHS=$(filter edsp media) + arm + ;; + armv7) + ALL_ARCHS=$(filter edsp media neon) + arm + ;; + *) + unoptimized + ;; +esac diff --git a/libs.mk b/libs.mk index f904a4a216ae431c05ee738bd50d1384a906e930..674571add440d112ac4b78303ceb790ee487c3b2 100644 --- a/libs.mk +++ b/libs.mk @@ -91,6 +91,7 @@ endif $(eval $(if $(filter universal%,$(TOOLCHAIN)),LIPO_LIBVPX,BUILD_LIBVPX):=yes) CODEC_SRCS-$(BUILD_LIBVPX) += build/make/version.sh +CODEC_SRCS-$(BUILD_LIBVPX) += build/make/rtcd.sh CODEC_SRCS-$(BUILD_LIBVPX) += vpx/vpx_integer.h CODEC_SRCS-$(BUILD_LIBVPX) += vpx_ports/asm_offsets.h CODEC_SRCS-$(BUILD_LIBVPX) += vpx_ports/vpx_timer.h @@ -185,6 +186,7 @@ vpx.vcproj: $(CODEC_SRCS) vpx.def PROJECTS-$(BUILD_LIBVPX) += vpx.vcproj vpx.vcproj: vpx_config.asm +vpx.vcproj: vpx_rtcd.h endif else @@ -351,6 +353,18 @@ endif $(shell $(SRC_PATH_BARE)/build/make/version.sh "$(SRC_PATH_BARE)" $(BUILD_PFX)vpx_version.h) CLEAN-OBJS += $(BUILD_PFX)vpx_version.h +# +# Rule to generate runtime cpu detection files +# +$(OBJS-yes:.o=.d): vpx_rtcd.h +vpx_rtcd.h: $(sort $(filter %rtcd_defs.sh,$(CODEC_SRCS))) + @echo " [CREATE] $@" + $(qexec)$(SRC_PATH_BARE)/build/make/rtcd.sh --arch=$(TGT_ISA) \ + --sym=vpx_rtcd \ + --config=$(target)$(if $(FAT_ARCHS),,-$(TOOLCHAIN)).mk \ + $(RTCD_OPTIONS) $^ > $@ +CLEAN-OBJS += $(BUILD_PFX)vpx_rtcd.h + CODEC_DOC_SRCS += vpx/vpx_codec.h \ vpx/vpx_decoder.h \ vpx/vpx_encoder.h \ diff --git a/vp8/common/generic/systemdependent.c b/vp8/common/generic/systemdependent.c index 1798e6524ceb10dd42fb53bece361755b01cbac2..b71ef750df084e943cbfaa051d548759b3d6b2d2 100644 --- a/vp8/common/generic/systemdependent.c +++ b/vp8/common/generic/systemdependent.c @@ -10,6 +10,7 @@ #include "vpx_ports/config.h" +#include "vpx_rtcd.h" #include "vp8/common/g_common.h" #include "vp8/common/subpixel.h" #include "vp8/common/loopfilter.h" @@ -140,4 +141,6 @@ void vp8_machine_specific_config(VP8_COMMON *ctx) { #if ARCH_ARM vp8_arch_arm_common_init(ctx); #endif + + vpx_rtcd(); } diff --git a/vp8/common/rtcd.c b/vp8/common/rtcd.c new file mode 100644 index 0000000000000000000000000000000000000000..4980f48ad95d60edbe55cf1333133b7a50494788 --- /dev/null +++ b/vp8/common/rtcd.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2011 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#include "vpx_config.h" +#define RTCD_C +#include "vpx_rtcd.h" + +#if CONFIG_MULTITHREAD && HAVE_PTHREAD_H +#include <pthread.h> +static void once(void (*func)(void)) +{ + static pthread_once_t lock = PTHREAD_ONCE_INIT; + pthread_once(&lock, func); +} + + +#elif CONFIG_MULTITHREAD && defined(_WIN32) +#include <windows.h> +static void once(void (*func)(void)) +{ + /* Using a static initializer here rather than InitializeCriticalSection() + * since there's no race-free context in which to execute it. Protecting + * it with an atomic op like InterlockedCompareExchangePointer introduces + * an x86 dependency, and InitOnceExecuteOnce requires Vista. + */ + static CRITICAL_SECTION lock = {(void *)-1, -1, 0, 0, 0, 0}; + static int done; + + EnterCriticalSection(&lock); + + if (!done) + { + func(); + done = 1; + } + + LeaveCriticalSection(&lock); +} + + +#else +/* No-op version that performs no synchronization. vpx_rtcd() is idempotent, + * so as long as your platform provides atomic loads/stores of pointers + * no synchronization is strictly necessary. + */ + +static void once(void (*func)(void)) +{ + static int done; + + if(!done) + { + func(); + done = 1; + } +} +#endif + + +void vpx_rtcd() +{ + once(setup_rtcd_internal); +} diff --git a/vp8/common/rtcd_defs.sh b/vp8/common/rtcd_defs.sh new file mode 100644 index 0000000000000000000000000000000000000000..95148c86f8fa2d8203bb29b5cf812b5bec3bd1c5 --- /dev/null +++ b/vp8/common/rtcd_defs.sh @@ -0,0 +1,6 @@ +common_forward_decls() { +cat <<EOF +struct blockd; +EOF +} +forward_decls common_forward_decls diff --git a/vp8/vp8_common.mk b/vp8/vp8_common.mk index c4bd283f82f15c170177ef35a5157bef6d6f6aae..8c9addc78f81a79229d1d632df801df6b0677b06 100644 --- a/vp8/vp8_common.mk +++ b/vp8/vp8_common.mk @@ -52,6 +52,8 @@ VP8_COMMON_SRCS-yes += common/recon.h VP8_COMMON_SRCS-yes += common/reconinter.h VP8_COMMON_SRCS-yes += common/reconintra.h VP8_COMMON_SRCS-yes += common/reconintra4x4.h +VP8_COMMON_SRCS-yes += common/rtcd.c +VP8_COMMON_SRCS-yes += common/rtcd_defs.sh VP8_COMMON_SRCS-yes += common/seg_common.h VP8_COMMON_SRCS-yes += common/seg_common.c VP8_COMMON_SRCS-yes += common/setupintrarecon.h