[?1034h# HG changeset patch
# User Petri Hintukainen <phintuka@users.sourceforge.net>
# Date 1183605802 -10800
# Node ID 2a249313af98cd5805bf8b9c99bf8b20ffe57b9a
# Parent  79a96eefa515c2a31436b95f5df0f0bd5a183247
libmpeg2 0.4.1: Use libmpeg2 CPU detection instead of xine-lib

diff -r 79a96eefa515 -r 2a249313af98 src/libmpeg2/Makefile.am
--- a/src/libmpeg2/Makefile.am	Wed Jul 04 03:09:58 2007 +0300
+++ b/src/libmpeg2/Makefile.am	Thu Jul 05 06:23:22 2007 +0300
@@ -4,6 +4,7 @@ xineplug_LTLIBRARIES = xineplug_decode_m
 
 xineplug_decode_mpeg2_la_SOURCES = \
 	cpu_state.c \
+	cpu_accel.c \
 	decode.c \
 	header.c \
 	idct.c \
diff -r 79a96eefa515 -r 2a249313af98 src/libmpeg2/cpu_accel.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/libmpeg2/cpu_accel.c	Thu Jul 05 06:23:22 2007 +0300
@@ -0,0 +1,220 @@
+/*
+ * cpu_accel.c
+ * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
+ * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ *
+ * This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
+ * See http://libmpeg2.sourceforge.net/ for updates.
+ *
+ * mpeg2dec 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 of the License, or
+ * (at your option) any later version.
+ *
+ * mpeg2dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+
+#include <inttypes.h>
+
+#include "mpeg2.h"
+#include "attributes.h"
+#include "mpeg2_internal.h"
+
+#if defined(ARCH_X86) || defined(__x86_64__)
+static inline uint32_t arch_accel (void)
+{
+    uint32_t eax, ebx, ecx, edx;
+    int AMD;
+    uint32_t caps;
+
+#if defined(__x86_64__) || (!defined(PIC) && !defined(__PIC__))
+#define cpuid(op,eax,ebx,ecx,edx)	\
+    __asm__ ("cpuid"			\
+	     : "=a" (eax),		\
+	       "=b" (ebx),		\
+	       "=c" (ecx),		\
+	       "=d" (edx)		\
+	     : "a" (op)			\
+	     : "cc")
+#else  /* PIC version : save ebx (not needed on x86_64) */
+#define cpuid(op,eax,ebx,ecx,edx)	\
+    __asm__ ("pushl %%ebx\n\t"		\
+	     "cpuid\n\t"		\
+	     "movl %%ebx,%1\n\t"	\
+	     "popl %%ebx"		\
+	     : "=a" (eax),		\
+	       "=r" (ebx),		\
+	       "=c" (ecx),		\
+	       "=d" (edx)		\
+	     : "a" (op)			\
+	     : "cc")
+#endif
+
+#ifndef __x86_64__ /* x86_64 supports the cpuid op */
+    __asm__ ("pushf\n\t"
+	     "pushf\n\t"
+	     "pop %0\n\t"
+	     "movl %0,%1\n\t"
+	     "xorl $0x200000,%0\n\t"
+	     "push %0\n\t"
+	     "popf\n\t"
+	     "pushf\n\t"
+	     "pop %0\n\t"
+	     "popf"
+	     : "=r" (eax),
+	       "=r" (ebx)
+	     :
+	     : "cc");
+
+    if (eax == ebx)		/* no cpuid */
+	return 0;
+#endif
+
+    cpuid (0x00000000, eax, ebx, ecx, edx);
+    if (!eax)			/* vendor string only */
+	return 0;
+
+    AMD = (ebx == 0x68747541) && (ecx == 0x444d4163) && (edx == 0x69746e65);
+
+    cpuid (0x00000001, eax, ebx, ecx, edx);
+    if (! (edx & 0x00800000))	/* no MMX */
+	return 0;
+
+    caps = MPEG2_ACCEL_X86_MMX;
+    if (edx & 0x02000000)	/* SSE - identical to AMD MMX extensions */
+	caps = MPEG2_ACCEL_X86_MMX | MPEG2_ACCEL_X86_MMXEXT;
+
+    cpuid (0x80000000, eax, ebx, ecx, edx);
+    if (eax < 0x80000001)	/* no extended capabilities */
+	return caps;
+
+    cpuid (0x80000001, eax, ebx, ecx, edx);
+
+    if (edx & 0x80000000)
+	caps |= MPEG2_ACCEL_X86_3DNOW;
+
+    if (AMD && (edx & 0x00400000))	/* AMD MMX extensions */
+	caps |= MPEG2_ACCEL_X86_MMXEXT;
+
+    return caps;
+}
+#endif /* ARCH_X86 */
+
+#if defined(ARCH_PPC) || defined(ARCH_SPARC)
+#include <signal.h>
+#include <setjmp.h>
+
+static sigjmp_buf jmpbuf;
+static volatile sig_atomic_t canjump = 0;
+
+static RETSIGTYPE sigill_handler (int sig)
+{
+    if (!canjump) {
+	signal (sig, SIG_DFL);
+	raise (sig);
+    }
+
+    canjump = 0;
+    siglongjmp (jmpbuf, 1);
+}
+
+#ifdef ARCH_PPC
+static uint32_t arch_accel (void)
+{
+    static RETSIGTYPE (* oldsig) (int);
+
+    oldsig = signal (SIGILL, sigill_handler);
+    if (sigsetjmp (jmpbuf, 1)) {
+	signal (SIGILL, oldsig);
+	return 0;
+    }
+
+    canjump = 1;
+
+#ifdef HAVE_ALTIVEC_H	/* gnu */
+#define VAND(a,b,c) "vand " #a "," #b "," #c "\n\t"
+#else			/* apple */
+#define VAND(a,b,c) "vand v" #a ",v" #b ",v" #c "\n\t"
+#endif
+    asm volatile ("mtspr 256, %0\n\t"
+		  VAND (0, 0, 0)
+		  :
+		  : "r" (-1));
+
+    canjump = 0;
+
+    signal (SIGILL, oldsig);
+    return MPEG2_ACCEL_PPC_ALTIVEC;
+}
+#endif /* ARCH_PPC */
+
+#ifdef ARCH_SPARC
+static uint32_t arch_accel (void)
+{
+    static RETSIGTYPE (* oldsig) (int);
+
+    oldsig = signal (SIGILL, sigill_handler);
+    if (sigsetjmp (jmpbuf, 1)) {
+	signal (SIGILL, oldsig);
+	return 0;
+    }
+
+    canjump = 1;
+
+    /* pdist %f0, %f0, %f0 */
+    __asm__ __volatile__(".word\t0x81b007c0");
+
+    canjump = 0;
+
+    if (sigsetjmp (jmpbuf, 1)) {
+	signal (SIGILL, oldsig);
+	return MPEG2_ACCEL_SPARC_VIS;
+    }
+
+    canjump = 1;
+
+    /* edge8n %g0, %g0, %g0 */
+    __asm__ __volatile__(".word\t0x81b00020");
+
+    canjump = 0;
+
+    signal (SIGILL, oldsig);
+    return MPEG2_ACCEL_SPARC_VIS | MPEG2_ACCEL_SPARC_VIS2;
+}
+#endif /* ARCH_SPARC */
+#endif /* ARCH_PPC || ARCH_SPARC */
+
+#ifdef ARCH_ALPHA
+static uint32_t arch_accel (void)
+{
+    uint64_t no_mvi;
+
+    asm volatile ("amask %1, %0"
+		  : "=r" (no_mvi)
+		  : "rI" (256));	/* AMASK_MVI */
+    return no_mvi ? MPEG2_ACCEL_ALPHA : (MPEG2_ACCEL_ALPHA |
+					 MPEG2_ACCEL_ALPHA_MVI);
+}
+#endif /* ARCH_ALPHA */
+
+uint32_t mpeg2_detect_accel (void)
+{
+    uint32_t accel;
+
+    accel = 0;
+/*#ifdef ACCEL_DETECT*/
+#if defined (ARCH_X86) || defined(__x86_64__) || defined (ARCH_PPC) || defined (ARCH_ALPHA) || defined (ARCH_SPARC)
+    accel = arch_accel ();
+#endif
+/*#endif*/
+    return accel;
+}
diff -r 79a96eefa515 -r 2a249313af98 src/libmpeg2/cpu_state.c
--- a/src/libmpeg2/cpu_state.c	Wed Jul 04 03:09:58 2007 +0300
+++ b/src/libmpeg2/cpu_state.c	Thu Jul 05 06:23:22 2007 +0300
@@ -26,13 +26,17 @@
 #include <stdlib.h>
 #include <inttypes.h>
 
+#include "mpeg2.h"
+#include "attributes.h"
 #include "mpeg2_internal.h"
-#include "xineutils.h"
+#if defined(ARCH_X86) || defined(__x86_64__)
+#include "mmx.h"
+#endif
 
 void (* mpeg2_cpu_state_save) (cpu_state_t * state) = NULL;
 void (* mpeg2_cpu_state_restore) (cpu_state_t * state) = NULL;
 
-#if defined(ARCH_X86) || defined(ARCH_X86_64)
+#if defined(ARCH_X86) || defined(__x86_64__)
 static void state_restore_mmx (cpu_state_t * state)
 {
     emms ();
@@ -109,15 +113,15 @@ static void state_restore_altivec (cpu_s
 }
 #endif
 
-void mpeg2_cpu_state_init (uint32_t mm_accel)
+void mpeg2_cpu_state_init (uint32_t accel)
 {
-#if defined(ARCH_X86) || defined(ARCH_X86_64)
-    if (mm_accel & MM_ACCEL_X86_MMX) {
+#if defined(ARCH_X86) || defined(__x86_64__)
+    if (accel & MPEG2_ACCEL_X86_MMX) {
 	mpeg2_cpu_state_restore = state_restore_mmx;
     }
 #endif
 #if defined (ARCH_PPC) && defined (ENABLE_ALTIVEC)
-    if (mm_accel & MM_ACCEL_PPC_ALTIVEC) {
+    if (accel & MPEG2_ACCEL_PPC_ALTIVEC) {
 	mpeg2_cpu_state_save = state_save_altivec;
 	mpeg2_cpu_state_restore = state_restore_altivec;
     }
diff -r 79a96eefa515 -r 2a249313af98 src/libmpeg2/decode.c
--- a/src/libmpeg2/decode.c	Wed Jul 04 03:09:58 2007 +0300
+++ b/src/libmpeg2/decode.c	Thu Jul 05 06:23:22 2007 +0300
@@ -57,14 +57,14 @@ void mpeg2_init (mpeg2dec_t * mpeg2dec,
 		 xine_video_port_t * output)
 {
   static int do_init = 1;
-  uint32_t mm_accel;
+  uint32_t accel;
 
     if (do_init) {
 	do_init = 0;
-	mm_accel = xine_mm_accel();
-	mpeg2_cpu_state_init (mm_accel);
-	mpeg2_idct_init (mm_accel);
-	mpeg2_mc_init (mm_accel);
+	accel = mpeg2_detect_accel();
+	mpeg2_cpu_state_init (accel);
+	mpeg2_idct_init (accel);
+	mpeg2_mc_init (accel);
 	libmpeg2_accel_scan(&mpeg2dec->accel, mpeg2_scan_norm, mpeg2_scan_alt);
     }
 
diff -r 79a96eefa515 -r 2a249313af98 src/libmpeg2/idct.c
--- a/src/libmpeg2/idct.c	Wed Jul 04 03:09:58 2007 +0300
+++ b/src/libmpeg2/idct.c	Thu Jul 05 06:23:22 2007 +0300
@@ -23,14 +23,14 @@
 
 #include "config.h"
 
-#include <stdio.h>
 #include <stdlib.h>
 #include <inttypes.h>
+
+#include <string.h>
 
 #include "mpeg2.h"
 #include "attributes.h"
 #include "mpeg2_internal.h"
-#include "xineutils.h"
 
 #define W1 2841 /* 2048 * sqrt (2) * cos (1 * pi / 16) */
 #define W2 2676 /* 2048 * sqrt (2) * cos (2 * pi / 16) */
@@ -253,51 +253,52 @@ static void mpeg2_zero_block_c (int16_t 
   memset( wblock, 0, sizeof(int16_t) * 64 );
 }
 
-void mpeg2_idct_init (uint32_t mm_accel)
-{
+void mpeg2_idct_init (uint32_t accel)
+{
+    mpeg2_idct = mpeg2_idct_c;
     mpeg2_zero_block = mpeg2_zero_block_c;
-
-#if defined(ARCH_X86) || defined(ARCH_X86_64)
-    if (mm_accel & MM_ACCEL_X86_MMXEXT) {
-#ifdef LOG
-	fprintf (stderr, "Using MMXEXT for IDCT transform\n");
-#endif
+#if defined(ARCH_X86) || defined(__x86_64__)
+    if (accel & MPEG2_ACCEL_X86_MMXEXT) {
 	mpeg2_idct_copy = mpeg2_idct_copy_mmxext;
 	mpeg2_idct_add = mpeg2_idct_add_mmxext;
 	mpeg2_idct     = mpeg2_idct_mmxext;
 	mpeg2_zero_block = mpeg2_zero_block_mmx;
 	mpeg2_idct_mmx_init ();
-    } else if (mm_accel & MM_ACCEL_X86_MMX) {
-#ifdef LOG
-	fprintf (stderr, "Using MMX for IDCT transform\n");
-#endif
+    } else if (accel & MPEG2_ACCEL_X86_MMX) {
 	mpeg2_idct_copy = mpeg2_idct_copy_mmx;
-	mpeg2_idct_add  = mpeg2_idct_add_mmx;
+	mpeg2_idct_add = mpeg2_idct_add_mmx;
 	mpeg2_idct      = mpeg2_idct_mmx;
 	mpeg2_zero_block = mpeg2_zero_block_mmx;
 	mpeg2_idct_mmx_init ();
     } else
 #endif
 #if defined (ARCH_PPC) && defined (ENABLE_ALTIVEC)
-    if (mm_accel & MM_ACCEL_PPC_ALTIVEC) {
-#ifdef LOG
-	fprintf (stderr, "Using altivec for IDCT transform\n");
-#endif
+    if (accel & MPEG2_ACCEL_PPC_ALTIVEC) {
 	mpeg2_idct_copy = mpeg2_idct_copy_altivec;
 	mpeg2_idct_add = mpeg2_idct_add_altivec;
 	mpeg2_idct_altivec_init ();
-	mpeg2_idct       = mpeg2_idct_c;
+    } else
+#endif
+#ifdef ARCH_ALPHA
+    if (accel & MPEG2_ACCEL_ALPHA_MVI) {
+	mpeg2_idct_copy = mpeg2_idct_copy_mvi;
+	mpeg2_idct_add = mpeg2_idct_add_mvi;
+	mpeg2_idct_alpha_init ();
+    } else if (accel & MPEG2_ACCEL_ALPHA) {
+	int i;
+
+	mpeg2_idct_copy = mpeg2_idct_copy_alpha;
+	mpeg2_idct_add = mpeg2_idct_add_alpha;
+	mpeg2_idct_alpha_init ();
+	for (i = -3840; i < 3840 + 256; i++)
+	    CLIP(i) = (i < 0) ? 0 : ((i > 255) ? 255 : i);
     } else
 #endif
     {
 	int i, j;
 
-#ifdef LOG
-	fprintf (stderr, "No accelerated IDCT transform found\n");
-#endif
 	mpeg2_idct_copy = mpeg2_idct_copy_c;
 	mpeg2_idct_add = mpeg2_idct_add_c;
-	mpeg2_idct      = mpeg2_idct_c;
 	for (i = -3840; i < 3840 + 256; i++)
 	    CLIP(i) = (i < 0) ? 0 : ((i > 255) ? 255 : i);
 	for (i = 0; i < 64; i++) {
diff -r 79a96eefa515 -r 2a249313af98 src/libmpeg2/idct_mmx.c
--- a/src/libmpeg2/idct_mmx.c	Wed Jul 04 03:09:58 2007 +0300
+++ b/src/libmpeg2/idct_mmx.c	Thu Jul 05 06:23:22 2007 +0300
@@ -23,7 +23,7 @@
 
 #include "config.h"
 
-#if defined(ARCH_X86) || defined(ARCH_X86_64)
+#if defined(ARCH_X86) || defined(__x86_64__)
 
 #include <inttypes.h>
 
diff -r 79a96eefa515 -r 2a249313af98 src/libmpeg2/motion_comp.c
--- a/src/libmpeg2/motion_comp.c	Wed Jul 04 03:09:58 2007 +0300
+++ b/src/libmpeg2/motion_comp.c	Thu Jul 05 06:23:22 2007 +0300
@@ -23,56 +23,41 @@
 
 #include "config.h"
 
-#include <stdio.h>
 #include <inttypes.h>
 
+#include "mpeg2.h"
+#include "attributes.h"
 #include "mpeg2_internal.h"
-#include "xineutils.h"
 
 mpeg2_mc_t mpeg2_mc;
 
-void mpeg2_mc_init (uint32_t mm_accel)
+void mpeg2_mc_init (uint32_t accel)
 {
-#if defined(ARCH_X86) || defined(ARCH_X86_64)
-    if (mm_accel & MM_ACCEL_X86_MMXEXT) {
-#ifdef LOG
-	fprintf (stderr, "Using MMXEXT for motion compensation\n");
-#endif
+#if defined(ARCH_X86) || defined(__x86_64__)
+    if (accel & MPEG2_ACCEL_X86_MMXEXT)
 	mpeg2_mc = mpeg2_mc_mmxext;
-    } else if (mm_accel & MM_ACCEL_X86_3DNOW) {
-#ifdef LOG
-	fprintf (stderr, "Using 3DNOW for motion compensation\n");
-#endif
+    else if (accel & MPEG2_ACCEL_X86_3DNOW)
 	mpeg2_mc = mpeg2_mc_3dnow;
-    } else if (mm_accel & MM_ACCEL_X86_MMX) {
-#ifdef LOG
-	fprintf (stderr, "Using MMX for motion compensation\n");
-#endif
+    else if (accel & MPEG2_ACCEL_X86_MMX)
 	mpeg2_mc = mpeg2_mc_mmx;
-    } else
+    else
 #endif
 #if defined (ARCH_PPC) && defined (ENABLE_ALTIVEC)
-    if (mm_accel & MM_ACCEL_PPC_ALTIVEC) {
-#ifdef LOG
-	fprintf (stderr, "Using altivec for motion compensation\n");
+    if (accel & MPEG2_ACCEL_PPC_ALTIVEC)
+	mpeg2_mc = mpeg2_mc_altivec;
+    else
 #endif
-	mpeg2_mc = mpeg2_mc_altivec;
-    } else
+#ifdef ARCH_ALPHA
+    if (accel & MPEG2_ACCEL_ALPHA)
+	mpeg2_mc = mpeg2_mc_alpha;
+    else
 #endif
 #ifdef ARCH_SPARC
-    if (mm_accel & MM_ACCEL_SPARC_VIS) {
-#ifdef LOG
-	fprintf (stderr, "Using VIS for motion compensation\n");
-#endif
+    if (accel & MPEG2_ACCEL_SPARC_VIS)
 	mpeg2_mc = mpeg2_mc_vis;
-    } else
-#endif
-    {
-#ifdef LOG
-	fprintf (stderr, "No accelerated motion compensation found\n");
+    else
 #endif
 	mpeg2_mc = mpeg2_mc_c;
-    }
 }
 
 #define avg2(a,b) ((a+b+1)>>1)
diff -r 79a96eefa515 -r 2a249313af98 src/libmpeg2/motion_comp_mmx.c
--- a/src/libmpeg2/motion_comp_mmx.c	Wed Jul 04 03:09:58 2007 +0300
+++ b/src/libmpeg2/motion_comp_mmx.c	Thu Jul 05 06:23:22 2007 +0300
@@ -23,7 +23,7 @@
 
 #include "config.h"
 
-#if defined(ARCH_X86) || defined(ARCH_X86_64)
+#if defined(ARCH_X86) || defined(__x86_64__)
 
 #include <inttypes.h>
 
diff -r 79a96eefa515 -r 2a249313af98 src/libmpeg2/mpeg2.h
--- a/src/libmpeg2/mpeg2.h	Wed Jul 04 03:09:58 2007 +0300
+++ b/src/libmpeg2/mpeg2.h	Thu Jul 05 06:23:22 2007 +0300
@@ -76,6 +76,18 @@ typedef struct mpeg2dec_s {
 } mpeg2dec_t ;
 
 
+#define MPEG2_ACCEL_X86_MMX 1
+#define MPEG2_ACCEL_X86_3DNOW 2
+#define MPEG2_ACCEL_X86_MMXEXT 4
+#define MPEG2_ACCEL_PPC_ALTIVEC 1
+#define MPEG2_ACCEL_ALPHA 1
+#define MPEG2_ACCEL_ALPHA_MVI 2
+#define MPEG2_ACCEL_SPARC_VIS 1
+#define MPEG2_ACCEL_SPARC_VIS2 2
+#define MPEG2_ACCEL_DETECT 0x80000000
+
+uint32_t mpeg2_accel (uint32_t accel);
+
 /* initialize mpegdec with a opaque user pointer */
 void mpeg2_init (mpeg2dec_t * mpeg2dec, 
 		 xine_video_port_t * output);
diff -r 79a96eefa515 -r 2a249313af98 src/libmpeg2/mpeg2_internal.h
--- a/src/libmpeg2/mpeg2_internal.h	Wed Jul 04 03:09:58 2007 +0300
+++ b/src/libmpeg2/mpeg2_internal.h	Thu Jul 05 06:23:22 2007 +0300
@@ -209,12 +209,12 @@ typedef struct cpu_state_s {
 } cpu_state_t;
 
 /* cpu_accel.c */
-/*uint32_t mpeg2_detect_accel (void);*/
+uint32_t mpeg2_detect_accel (void);
 
 /* cpu_state.c */
 extern void (* mpeg2_cpu_state_save) (cpu_state_t * state);
 extern void (* mpeg2_cpu_state_restore) (cpu_state_t * state);
-void mpeg2_cpu_state_init (uint32_t mm_accel);
+void mpeg2_cpu_state_init (uint32_t accel);
 
 /* header.c */
 extern uint8_t mpeg2_scan_norm[64];
@@ -230,7 +230,7 @@ extern void (* mpeg2_idct_add) (const in
 extern void (* mpeg2_idct_add) (const int last, int16_t * block, uint8_t * dest, int stride);
 extern void (* mpeg2_idct) (int16_t * block);
 extern void (* mpeg2_zero_block) (int16_t * block);
-void mpeg2_idct_init (uint32_t mm_accel);
+void mpeg2_idct_init (uint32_t accel);
 
 /* idct_mmx.c */
 void mpeg2_idct_copy_mmxext (int16_t * block, uint8_t * dest, int stride);
