Partial import of "New RTCD implementation" from master branch.
authorChristian Duvivier <cduvivier@google.com>
Wed, 8 Aug 2012 22:47:36 +0000 (15:47 -0700)
committerChristian Duvivier <cduvivier@google.com>
Wed, 8 Aug 2012 23:43:48 +0000 (16:43 -0700)
Latest version of all scripts/makefile but rtcd_defs.sh is empty, all
existing functions are still selected using the old/current way.

Change-Id: Ib92946a48a31d6c8d1d7359eca524bc1d3e66174

build/make/configure.sh
build/make/rtcd.sh [new file with mode: 0755]
libs.mk
vp8/common/generic/systemdependent.c
vp8/common/rtcd.c [new file with mode: 0644]
vp8/common/rtcd_defs.sh [new file with mode: 0644]
vp8/vp8_common.mk

index 552f8c1..be34778 100755 (executable)
@@ -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 (executable)
index 0000000..ddf9e09
--- /dev/null
@@ -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 f904a4a..674571a 100644 (file)
--- 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 \
index 1798e65..b71ef75 100644 (file)
@@ -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 (file)
index 0000000..4980f48
--- /dev/null
@@ -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 (file)
index 0000000..95148c8
--- /dev/null
@@ -0,0 +1,6 @@
+common_forward_decls() {
+cat <<EOF
+struct blockd;
+EOF
+}
+forward_decls common_forward_decls
index c4bd283..8c9addc 100644 (file)
@@ -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