748 changes: 748 additions & 0 deletions mythtv/libs/libmythtv/visualisations/goom/filters.c

Large diffs are not rendered by default.

54 changes: 54 additions & 0 deletions mythtv/libs/libmythtv/visualisations/goom/filters.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#ifndef FILTERS_H
#define FILTERS_H

#include "goomconfig.h"

#include "graphic.h"
#include "math.h"

typedef struct
{
int vitesse; /* 128 = vitesse nule... * * 256 = en arriere * hyper vite.. * * 0 = en avant hype vite. */
unsigned char pertedec;
unsigned char sqrtperte;
int middleX, middleY; /* milieu de l'effet */
char reverse; /* inverse la vitesse */
char mode; /* type d'effet à appliquer (cf les #define)
* * * * * ** @since June 2001 */
int hPlaneEffect; /* deviation horitontale */
int vPlaneEffect; /* deviation verticale */
/** @since April 2002 */
int waveEffect; /* applique une "surcouche" de wave effect */
int hypercosEffect; /* applique une "surcouche de hypercos effect
*/

char noisify; /* ajoute un bruit a la transformation */
}
ZoomFilterData;


#define NORMAL_MODE 0
#define WAVE_MODE 1
#define CRYSTAL_BALL_MODE 2
#define SCRUNCH_MODE 3
#define AMULETTE_MODE 4
#define WATER_MODE 5
#define HYPERCOS1_MODE 6
#define HYPERCOS2_MODE 7
#define YONLY_MODE 8
#define SPEEDWAY_MODE 9

void pointFilter (guint32 * pix1, Color c, float t1, float t2, float t3, float t4, guint32 cycle);

/* filtre de zoom :
* le contenu de pix1 est copie dans pix2.
* zf : si non NULL, configure l'effet.
* resx,resy : taille des buffers.
*/

void zoomFilterFastRGB (guint32 * pix1, guint32 * pix2, ZoomFilterData * zf, guint32 resx, guint32 resy, int switchIncr, float switchMult);

#define SIN_MUL 1
#define SIN_ADD 2

#endif
952 changes: 952 additions & 0 deletions mythtv/libs/libmythtv/visualisations/goom/goom_core.c

Large diffs are not rendered by default.

19 changes: 19 additions & 0 deletions mythtv/libs/libmythtv/visualisations/goom/goom_core.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#ifndef _GOOMCORE_H
#define _GOOMCORE_H

#include "goomconfig.h"

#define NB_FX 10

void goom_init (guint32 resx, guint32 resy, int cinemascope);
void goom_set_resolution (guint32 resx, guint32 resy, int cinemascope);

/*
* forceMode == 0 : do nothing
* forceMode == -1 : lock the FX
* forceMode == 1..NB_FX : force a switch to FX n°forceMode
*/
guint32 *goom_update (gint16 data[2][512], int forceMode);
void goom_close (void);

#endif
37 changes: 37 additions & 0 deletions mythtv/libs/libmythtv/visualisations/goom/goom_tools.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#ifndef _GOOMTOOLS_H
#define _GOOMTOOLS_H

#if !defined( M_PI )
#define M_PI 3.14159265358979323846
#endif

#define NB_RAND 0x10000

/* in graphic.c */
extern int *rand_tab;
static unsigned short rand_pos;

#define RAND_INIT(i) \
srand (i) ;\
if (!rand_tab) rand_tab = (int *) malloc (NB_RAND * sizeof(int)) ;\
rand_pos = 1 ;\
while (rand_pos != 0) rand_tab [rand_pos++] = rand () ;


static inline int RAND() {
++rand_pos;
return rand_tab[rand_pos];
}

#define RAND_CLOSE()\
free (rand_tab);\
rand_tab = 0;


//#define iRAND(i) ((guint32)((float)i * RAND()/RAND_MAX))
#define iRAND(i) (RAND()%i)

//inline unsigned int RAND(void);
//inline unsigned int iRAND(int i);

#endif
39 changes: 39 additions & 0 deletions mythtv/libs/libmythtv/visualisations/goom/goomconfig.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@

//#define VERSION "1.9.2"
//#define _DEBUG

#define COLOR_BGRA
//#define COLOR_ARGB

#ifdef COLOR_BGRA
/** position des composantes **/
#define ROUGE 2
#define BLEU 0
#define VERT 1
#define ALPHA 3
#else
#define ROUGE 1
#define BLEU 3
#define VERT 2
#define ALPHA 0
#endif


// target
#define XMMS_PLUGIN
//#define STANDALONE

//#define POWERPC

//#define HAVE_ATHLON

//#define VERBOSE

#ifndef guint32
#define guint8 unsigned char
#define guin16 unsigned short
#define guint32 unsigned int
#define gint8 signed char
#define gint16 signed short int
#define gint32 signed int
#endif
30 changes: 30 additions & 0 deletions mythtv/libs/libmythtv/visualisations/goom/graphic.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include "graphic.h"

const Color BLACK = { 0, 0, 0 };
const Color WHITE = { 0xff, 0xff, 0xff };
const Color RED = { 0xff, 0, 0 };
const Color GREEN = { 0, 0xff, 0 };
const Color BLUE = { 0, 0, 0xff };
const Color YELLOW = { 0xff, 0xff, 0x33 };
const Color ORANGE = { 0xff, 0xcc, 0x00 };
const Color VIOLET = { 0x55, 0x00, 0xff };

unsigned int SIZE;
unsigned int HEIGHT;
unsigned int WIDTH;

int *rand_tab = 0;
//unsigned short int rand_pos = 0;
/*
inline unsigned int RAND(void)
{
rand_pos++;
return rand_tab[rand_pos];
}
inline unsigned int iRAND(int i)
{
rand_pos++;
return (rand_tab[rand_pos])%i;
}
*/
24 changes: 24 additions & 0 deletions mythtv/libs/libmythtv/visualisations/goom/graphic.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#ifndef GRAPHIC_H
#define GRAPHIC_H

typedef unsigned int Uint;

typedef struct
{
unsigned short r, v, b;
}
Color;

extern const Color BLACK;
extern const Color WHITE;
extern const Color RED;
extern const Color BLUE;
extern const Color GREEN;
extern const Color YELLOW;
extern const Color ORANGE;
extern const Color VIOLET;

//inline void setPixelRGB (Uint * buffer, Uint x, Uint y, Color c);
//inline void getPixelRGB (Uint * buffer, Uint x, Uint y, Color * c);

#endif /* GRAPHIC_H */
549 changes: 549 additions & 0 deletions mythtv/libs/libmythtv/visualisations/goom/ifs.c

Large diffs are not rendered by default.

33 changes: 33 additions & 0 deletions mythtv/libs/libmythtv/visualisations/goom/ifs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* File created 11 april 2002 by JeKo <jeko@free.fr>
*/

#ifndef IFS_H
#define IFS_H

#include "goomconfig.h"

typedef struct _ifsPoint
{
gint32 x, y;
}
IFSPoint;

// init ifs for a (width)x(height) output.
void init_ifs (int width, int height);

// draw an ifs on the buffer (which size is width * height)
// increment means that we draw 1/increment of the ifs's points
void ifs_update (guint32 * buffer, guint32 * back, int width, int height, int increment);

// free all ifs's data.
void release_ifs (void);


/* DONT USE !!! deprecated
* return a an array of points.
* WARNING !!! do not free it !!! it also has an internal use..
*/
IFSPoint *draw_ifs (int *nbPoints);

#endif
268 changes: 268 additions & 0 deletions mythtv/libs/libmythtv/visualisations/goom/ifs_display.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,268 @@
#include "ifs.h"
#include "goomconfig.h"

#ifdef MMX
#include "mmx.h"
#endif

#include "goom_tools.h"

void
ifs_update (guint32 * data, guint32 * back, int width, int height,
int increment)
{
static int couleur = 0xc0c0c0c0;
static int v[4] = { 2, 4, 3, 2 };
static int col[4] = { 2, 4, 3, 2 };

#define MOD_MER 0
#define MOD_FEU 1
#define MOD_MERVER 2
static int mode = MOD_MERVER;
static int justChanged = 0;
static int cycle = 0;
int cycle10;

int nbpt;
IFSPoint *points;
int i;

int couleursl = couleur;

cycle++;
if (cycle >= 80)
cycle = 0;

if (cycle < 40)
cycle10 = cycle / 10;
else
cycle10 = 7 - cycle / 10;

{
unsigned char *tmp = (unsigned char *) &couleursl;

for (i = 0; i < 4; i++) {
*tmp = (*tmp) >> cycle10;
tmp++;
}
}

points = draw_ifs (&nbpt);
nbpt--;

#ifdef MMX
movd_m2r (couleursl, mm1);
punpckldq_r2r (mm1, mm1);
for (i = 0; i < nbpt; i += increment) {
int x = points[i].x;
int y = points[i].y;

if ((x < width) && (y < height) && (x > 0) && (y > 0)) {
int pos = x + (y * width);
movd_m2r (back[pos], mm0);
paddusb_r2r (mm1, mm0);
movd_r2m (mm0, data[pos]);
}
}
emms();/*__asm__ __volatile__ ("emms");*/
#else
for (i = 0; i < nbpt; i += increment) {
int x = (int) points[i].x & 0x7fffffff;
int y = (int) points[i].y & 0x7fffffff;

if ((x < width) && (y < height)) {
int pos = x + (int) (y * width);
int tra = 0, i = 0;
unsigned char *bra = (unsigned char *) &back[pos];
unsigned char *dra = (unsigned char *) &data[pos];
unsigned char *cra = (unsigned char *) &couleursl;

for (; i < 4; i++) {
tra = *cra;
tra += *bra;
if (tra > 255)
tra = 255;
*dra = tra;
++dra;
++cra;
++bra;
}
}
}
#endif /*MMX*/
justChanged--;

col[ALPHA] = couleur >> (ALPHA * 8) & 0xff;
col[BLEU] = couleur >> (BLEU * 8) & 0xff;
col[VERT] = couleur >> (VERT * 8) & 0xff;
col[ROUGE] = couleur >> (ROUGE * 8) & 0xff;

if (mode == MOD_MER) {
col[BLEU] += v[BLEU];
if (col[BLEU] > 255) {
col[BLEU] = 255;
v[BLEU] = -(RAND() % 4) - 1;
}
if (col[BLEU] < 32) {
col[BLEU] = 32;
v[BLEU] = (RAND() % 4) + 1;
}

col[VERT] += v[VERT];
if (col[VERT] > 200) {
col[VERT] = 200;
v[VERT] = -(RAND() % 3) - 2;
}
if (col[VERT] > col[BLEU]) {
col[VERT] = col[BLEU];
v[VERT] = v[BLEU];
}
if (col[VERT] < 32) {
col[VERT] = 32;
v[VERT] = (RAND() % 3) + 2;
}

col[ROUGE] += v[ROUGE];
if (col[ROUGE] > 64) {
col[ROUGE] = 64;
v[ROUGE] = -(RAND () % 4) - 1;
}
if (col[ROUGE] < 0) {
col[ROUGE] = 0;
v[ROUGE] = (RAND () % 4) + 1;
}

col[ALPHA] += v[ALPHA];
if (col[ALPHA] > 0) {
col[ALPHA] = 0;
v[ALPHA] = -(RAND () % 4) - 1;
}
if (col[ALPHA] < 0) {
col[ALPHA] = 0;
v[ALPHA] = (RAND () % 4) + 1;
}

if (((col[VERT] > 32) && (col[ROUGE] < col[VERT] + 40)
&& (col[VERT] < col[ROUGE] + 20) && (col[BLEU] < 64)
&& (RAND () % 20 == 0)) && (justChanged < 0)) {
mode = (RAND () % 3) ? MOD_FEU : MOD_MERVER;
justChanged = 250;
}
}
else if (mode == MOD_MERVER) {
col[BLEU] += v[BLEU];
if (col[BLEU] > 128) {
col[BLEU] = 128;
v[BLEU] = -(RAND () % 4) - 1;
}
if (col[BLEU] < 16) {
col[BLEU] = 16;
v[BLEU] = (RAND () % 4) + 1;
}

col[VERT] += v[VERT];
if (col[VERT] > 200) {
col[VERT] = 200;
v[VERT] = -(RAND () % 3) - 2;
}
if (col[VERT] > col[ALPHA]) {
col[VERT] = col[ALPHA];
v[VERT] = v[ALPHA];
}
if (col[VERT] < 32) {
col[VERT] = 32;
v[VERT] = (RAND () % 3) + 2;
}

col[ROUGE] += v[ROUGE];
if (col[ROUGE] > 128) {
col[ROUGE] = 128;
v[ROUGE] = -(RAND () % 4) - 1;
}
if (col[ROUGE] < 0) {
col[ROUGE] = 0;
v[ROUGE] = (RAND () % 4) + 1;
}

col[ALPHA] += v[ALPHA];
if (col[ALPHA] > 255) {
col[ALPHA] = 255;
v[ALPHA] = -(RAND () % 4) - 1;
}
if (col[ALPHA] < 0) {
col[ALPHA] = 0;
v[ALPHA] = (RAND () % 4) + 1;
}

if (((col[VERT] > 32) && (col[ROUGE] < col[VERT] + 40)
&& (col[VERT] < col[ROUGE] + 20) && (col[BLEU] < 64)
&& (RAND () % 20 == 0)) && (justChanged < 0)) {
mode = (RAND () % 3) ? MOD_FEU : MOD_MER;
justChanged = 250;
}
}
else if (mode == MOD_FEU) {

col[BLEU] += v[BLEU];
if (col[BLEU] > 64) {
col[BLEU] = 64;
v[BLEU] = -(RAND () % 4) - 1;
}
if (col[BLEU] < 0) {
col[BLEU] = 0;
v[BLEU] = (RAND () % 4) + 1;
}

col[VERT] += v[VERT];
if (col[VERT] > 200) {
col[VERT] = 200;
v[VERT] = -(RAND () % 3) - 2;
}
if (col[VERT] > col[ROUGE] + 20) {
col[VERT] = col[ROUGE] + 20;
v[VERT] = -(RAND () % 3) - 2;
v[ROUGE] = (RAND () % 4) + 1;
v[BLEU] = (RAND () % 4) + 1;
}
if (col[VERT] < 0) {
col[VERT] = 0;
v[VERT] = (RAND () % 3) + 2;
}

col[ROUGE] += v[ROUGE];
if (col[ROUGE] > 255) {
col[ROUGE] = 255;
v[ROUGE] = -(RAND () % 4) - 1;
}
if (col[ROUGE] > col[VERT] + 40) {
col[ROUGE] = col[VERT] + 40;
v[ROUGE] = -(RAND () % 4) - 1;
}
if (col[ROUGE] < 0) {
col[ROUGE] = 0;
v[ROUGE] = (RAND () % 4) + 1;
}

col[ALPHA] += v[ALPHA];
if (col[ALPHA] > 0) {
col[ALPHA] = 0;
v[ALPHA] = -(RAND () % 4) - 1;
}
if (col[ALPHA] < 0) {
col[ALPHA] = 0;
v[ALPHA] = (RAND () % 4) + 1;
}

if (((col[ROUGE] < 64) && (col[VERT] > 32) && (col[VERT] < col[BLEU])
&& (col[BLEU] > 32)
&& (RAND () % 20 == 0)) && (justChanged < 0)) {
mode = (RAND () % 2) ? MOD_MER : MOD_MERVER;
justChanged = 250;
}
}

couleur = (col[ALPHA] << (ALPHA * 8))
| (col[BLEU] << (BLEU * 8))
| (col[VERT] << (VERT * 8))
| (col[ROUGE] << (ROUGE * 8));
}
247 changes: 247 additions & 0 deletions mythtv/libs/libmythtv/visualisations/goom/lines.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
/*
* lines.c
*/

#include "lines.h"
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include "goom_tools.h"
#include "drawmethods.h"

extern unsigned int resolx, c_resoly;

static inline unsigned char
lighten (unsigned char value, float power)
{
int val = value;
float t = (float) val * log10(power) / 2.0;

if (t > 0) {
val = (int) t; // (32.0f * log (t));
if (val > 255)
val = 255;
if (val < 0)
val = 0;
return val;
}
else {
return 0;
}
}

static void
lightencolor (int *col, float power)
{
unsigned char *color;

color = (unsigned char *) col;
*color = lighten (*color, power);
color++;
*color = lighten (*color, power);
color++;
*color = lighten (*color, power);
color++;
*color = lighten (*color, power);
}

static void
genline (int id, float param, GMUnitPointer * l, int rx, int ry)
{
int i;

switch (id) {
case GML_HLINE:
for (i = 0; i < 512; i++) {
l[i].x = ((float) i * rx) / 512.0f;
l[i].y = param;
l[i].angle = M_PI / 2.0f;
}
return;
case GML_VLINE:
for (i = 0; i < 512; i++) {
l[i].y = ((float) i * ry) / 512.0f;
l[i].x = param;
l[i].angle = 0.0f;
}
return;
case GML_CIRCLE:
for (i = 0; i < 512; i++) {
float cosa, sina;

l[i].angle = 2.0f * M_PI * (float) i / 512.0f;
cosa = param * cos (l[i].angle);
sina = param * sin (l[i].angle);
l[i].x = ((float) rx / 2.0f) + cosa;
l[i].y = (float) ry / 2.0f + sina;
}
return;
}
}

static guint32 getcouleur (int mode)
{
switch (mode) {
case GML_RED:
return (230 << (ROUGE * 8)) | (120 << (VERT * 8)) | (10 << (BLEU * 8));
case GML_ORANGE_J:
return (120 << (VERT * 8)) | (252 << (ROUGE * 8)) | (10 << (BLEU * 8));
case GML_ORANGE_V:
return (160 << (VERT * 8)) | (236 << (ROUGE * 8)) | (40 << (BLEU * 8));
case GML_BLEUBLANC:
return (40 << (BLEU * 8)) | (220 << (ROUGE * 8)) | (140 << (VERT * 8));
case GML_VERT:
return (200 << (VERT * 8)) | (80 << (ROUGE * 8)) | (10 << (BLEU * 8));
case GML_BLEU:
return (250 << (BLEU * 8)) | (30 << (VERT * 8)) | (80 << (ROUGE * 8));
case GML_BLACK:
return 0x5 << (BLEU * 8);
}
return 0;
}

void
goom_lines_set_res (GMLine * gml, int rx, int ry)
{
if (gml != NULL) {
//int i;

gml->screenX = rx;
gml->screenY = ry;

genline (gml->IDdest, gml->param, gml->points2, rx, ry);
}
}


static void
goom_lines_move (GMLine * l)
{
int i;
unsigned char *c1, *c2;

for (i = 0; i < 512; i++) {
l->points[i].x = (l->points2[i].x + 39.0f * l->points[i].x) / 40.0f;
l->points[i].y = (l->points2[i].y + 39.0f * l->points[i].y) / 40.0f;
l->points[i].angle =
(l->points2[i].angle + 39.0f * l->points[i].angle) / 40.0f;
}

c1 = (unsigned char *) &l->color;
c2 = (unsigned char *) &l->color2;
for (i = 0; i < 4; i++) {
int cc1, cc2;

cc1 = *c1;
cc2 = *c2;
*c1 = (unsigned char) ((cc1 * 63 + cc2) >> 6);
++c1;
++c2;
}

l->power += l->powinc;
if (l->power < 1.1f) {
l->power = 1.1f;
l->powinc = (float) (iRAND (20) + 10) / 300.0f;
}
if (l->power > 17.5f) {
l->power = 17.5f;
l->powinc = -(float) (iRAND (20) + 10) / 300.0f;
}

l->amplitude = (99.0f * l->amplitude + l->amplitudeF) / 100.0f;
}

void
goom_lines_switch_to (GMLine * gml, int IDdest,
float param, float amplitude, int col)
{
genline (IDdest, param, gml->points2, gml->screenX, gml->screenY);
gml->IDdest = IDdest;
gml->param = param;
gml->amplitudeF = amplitude;
gml->color2 = getcouleur (col);
// printf ("couleur %d : %x\n",col,gml->color2);
}

GMLine *
goom_lines_init (int rx, int ry,
int IDsrc, float paramS, int coulS,
int IDdest, float paramD, int coulD)
{
//int i;
//unsigned char *color;
//unsigned char power = 4;

GMLine *l = (GMLine *) malloc (sizeof (GMLine));

l->points = (GMUnitPointer *) malloc (512 * sizeof (GMUnitPointer));
l->points2 = (GMUnitPointer *) malloc (512 * sizeof (GMUnitPointer));
l->nbPoints = 512;

l->IDdest = IDdest;
l->param = paramD;

l->amplitude = l->amplitudeF = 1.0f;

genline (IDsrc, paramS, l->points, rx, ry);
genline (IDdest, paramD, l->points2, rx, ry);

l->color = getcouleur (coulS);
l->color2 = getcouleur (coulD);

l->screenX = rx;
l->screenY = ry;

l->power = 0.0f;
l->powinc = 0.01f;

goom_lines_switch_to (l, IDdest, paramD, 1.0f, coulD);

return l;
}

void
goom_lines_free (GMLine ** l)
{
free ((*l)->points);
free ((*l)->points2);
free (*l);
l = NULL;
}

void
goom_lines_draw (GMLine * line, gint16 data[512], unsigned int *p)
{
if (line != NULL) {
int i, x1, y1;
guint32 color = line->color;
GMUnitPointer *pt = &(line->points[0]);

float cosa = cos (pt->angle) / 1000.0f;
float sina = sin (pt->angle) / 1000.0f;

lightencolor ((int *)&color, line->power);

x1 = (int) (pt->x + cosa * line->amplitude * data[0]);
y1 = (int) (pt->y + sina * line->amplitude * data[0]);

for (i = 1; i < 512; i++) {
int x2, y2;
GMUnitPointer *pt = &(line->points[i]);

float cosa = cos (pt->angle) / 1000.0f;
float sina = sin (pt->angle) / 1000.0f;

x2 = (int) (pt->x + cosa * line->amplitude * data[i]);
y2 = (int) (pt->y + sina * line->amplitude * data[i]);

draw_line ((int *)p, x1, y1, x2, y2, color, line->screenX, line->screenY);
DRAWMETHOD_DONE ();

x1 = x2;
y1 = y2;
}
goom_lines_move (line);
}
}
69 changes: 69 additions & 0 deletions mythtv/libs/libmythtv/visualisations/goom/lines.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* lines.h
* iGoom
*
* Created by guillaum on Tue Aug 14 2001.
* Copyright (c) 2001 ios. All rights reserved.
*/

#include "graphic.h"
#include "goomconfig.h"

typedef struct _GMUNITPOINTER
{
float x;
float y;
float angle;
} GMUnitPointer;

// tableau de points
typedef struct _GMLINE
{
GMUnitPointer *points;
GMUnitPointer *points2;
int IDdest;
float param;
float amplitudeF;
float amplitude;

int nbPoints;
guint32 color;
guint32 color2;

int screenX;
int screenY;

float power;
float powinc;
} GMLine;

// les ID possibles
#define GML_CIRCLE 0
// (param = radius)

#define GML_HLINE 1
// (param = y)

#define GML_VLINE 2
// (param = x)

// les modes couleur possible (si tu mets un autre c'est noir)

#define GML_BLEUBLANC 0
#define GML_RED 1
#define GML_ORANGE_V 2
#define GML_ORANGE_J 3
#define GML_VERT 4
#define GML_BLEU 5
#define GML_BLACK 6

/* construit un effet de line (une ligne horitontale pour commencer) */
GMLine *goom_lines_init (int rx, int ry, int IDsrc, float paramS, int modeCoulSrc, int IDdest, float paramD, int modeCoulDest);

void goom_lines_switch_to (GMLine * gml, int IDdest, float param, float amplitude, int modeCoul);

void goom_lines_set_res (GMLine * gml, int rx, int ry);

void goom_lines_free (GMLine ** gml);

void goom_lines_draw (GMLine * gml, gint16 data[512], unsigned int *p);
26 changes: 26 additions & 0 deletions mythtv/libs/libmythtv/visualisations/goom/mathtools.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#define _double2fixmagic (68719476736.0*1.5)
//2^36 * 1.5, (52-_shiftamt=36) uses limited precisicion to floor
#define _shiftamt 16
//16.16 fixed point representation,

#ifdef BigEndian_
#define iexp_ 0
#define iman_ 1
#else
#define iexp_ 1
#define iman_ 0
#endif //BigEndian_

//#ifdef HAVE_MMX
//#define F2I(dbl,i)
//{double d = dbl + _double2fixmagic; i = ((int*)&d)[iman_] >> _shiftamt; }
//#else
#define F2I(dbl,i) i=(int)dbl;
//#endif

#if 0
#define SINCOS(f,s,c) \
__asm__ __volatile__ ("fsincos" : "=t" (c), "=u" (s) : "0" (f))
#else
#define SINCOS(f,s,c) {s=sin(f);c=cos(f);}
#endif
15 changes: 15 additions & 0 deletions mythtv/libs/libmythtv/visualisations/goom/mmx.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#ifndef GOOM_MMX_H

#include <mythconfig.h>
#include "libavcodec/x86/mmx.h"

int mm_support(void);

#define MM_MMX 0x0001 /* standard MMX */
#define MM_3DNOW 0x0004 /* AMD 3DNOW */
#define MM_MMXEXT 0x0002 /* SSE integer functions or AMD MMX ext */
#define MM_SSE 0x0008 /* SSE functions */
#define MM_SSE2 0x0010 /* PIV SSE2 functions */
#define MM_3DNOWEXT 0x0020 /* AMD 3DNowExt */

#endif
203 changes: 203 additions & 0 deletions mythtv/libs/libmythtv/visualisations/goom/mythgoom.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
#include "mythgoom.h"

#ifdef SDL_SUPPORT

#include <cmath>
#include <cstdlib>

#include <iostream>
using namespace std;

#include <QPainter>

#include <compat.h>
#include <mythcontext.h>
#include <mythlogging.h>

extern "C" {
#include "goom_tools.h"
#include "goom_core.h"
}

Goom::Goom(long int winid)
{
fps = 20;

surface = NULL;
buffer = NULL;

char SDL_windowhack[32];
//char SDL_windowhack[sizeof(long int)];
sprintf(SDL_windowhack, "%ld", winid);
setenv("SDL_WINDOWID", SDL_windowhack, 1);

if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0)
{
LOG(VB_GENERAL, LOG_ERR, "Unable to init SDL");
return;
}

SDL_ShowCursor(0);

goom_init(800, 600, 0);

scalew = gCoreContext->GetNumSetting("VisualScaleWidth", 2);
scaleh = gCoreContext->GetNumSetting("VisualScaleHeight", 2);

if (scaleh > 2)
scaleh = 2;
if (scaleh < 1)
scaleh = 1;

if (scalew > 2)
scalew = 2;
if (scalew < 1)
scalew = 1;
}

Goom::~Goom()
{
goom_close();
SDL_Quit();

unsetenv("SDL_WINDOWID");
}

void Goom::resize(const QSize &newsize)
{
size = newsize;

size.setHeight((size.height() / 2) * 2);
size.setWidth((size.width() / 2) * 2);

surface = SDL_SetVideoMode(size.width(), size.height(), 32, 0 /* SDL_ANYFORMAT */);
goom_set_resolution(size.width() / scalew, size.height() / scaleh, 0);
}

bool Goom::process(VisualNode *node)
{
if (!node || node->length == 0 || !surface)
return true;

int numSamps = 512;
if (node->length < 512)
numSamps = node->length;

signed short int data[2][512];

int i = 0;
for (i = 0; i < numSamps; i++)
{
data[0][i] = node->left[i];
if (node->right)
data[1][i] = node->right[i];
else
data[1][i] = data[0][i];
}

for (; i < 512; i++)
{
data[0][i] = 0;
data[1][i] = 0;
}

buffer = goom_update(data, 0);

return false;
}

bool Goom::draw(QPainter *p, const QColor &back)
{
(void)p;
(void)back;

if (!surface)
{
LOG(VB_GENERAL, LOG_ERR, "No sdl surface");
return false;
}

if (!buffer)
return false;

if (scalew != 1 || scaleh != 1)
{
SDL_LockSurface(surface);

register int *d = (int*)surface->pixels;
register int *s = (int*)buffer;

int sw = (size.width() / scalew) << 2;
int sw2 = surface->pitch;
int swd = sw2 - sw * scalew;

long fin = (long)s;
long fd = (long)d + (sw2 * size.height());

while ((long)d < fd) {
fin += sw;
if (scalew == 2)
{
while ((long)s < fin) {
register long col = *(s++);
*(d++) = col; *(d++) = col;
}
}
else
{
while ((long)s < fin) {
register long col = *(s++);
*(d++) = col;
}
}
d = (int*)((char*)d + swd);

if (scaleh == 2)
{
memcpy(d, ((char*)d) - sw2, sw2);
d = (int*)((char*)d + sw2);
}
}
}
else
{
SDL_Surface *tmpsurf = SDL_CreateRGBSurfaceFrom(buffer, size.width(),
size.height(), 32,
size.width() * 4,
0x00ff0000, 0x0000ff00,
0x000000ff, 0x00000000);
SDL_BlitSurface(tmpsurf, NULL, surface, NULL);
SDL_FreeSurface(tmpsurf);
}

SDL_UnlockSurface(surface);
SDL_Flip(surface);

return false;
}

static class GoomFactory : public VisFactory
{
public:
const QString &name(void) const
{
static QString name("Goom");
return name;
}

uint plugins(QStringList *list) const
{
*list << name();
return 1;
}

VisualBase *create(MainVisual *parent, long int winid, const QString &pluginName) const
{
(void)parent;
(void)pluginName;
return new Goom(winid);
}
}GoomFactory;


#endif
34 changes: 34 additions & 0 deletions mythtv/libs/libmythtv/visualisations/goom/mythgoom.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#ifndef MYTHGOOM
#define MYTHGOOM

#include "../mainvisual.h"
#include "../config.h"

using namespace std;

#ifdef SDL_SUPPORT
#include <SDL.h>

class Goom : public VisualBase
{
public:
Goom(long int winid);
virtual ~Goom();

void resize(const QSize &size);
bool process(VisualNode *node);
bool draw(QPainter *p, const QColor &back);
void handleKeyPress(const QString &action) {(void) action;}

private:
QSize size;

SDL_Surface *surface;

unsigned int *buffer;
int scalew, scaleh;
};

#endif //SDL_SUPPORT

#endif //MYTHGOOM
133 changes: 133 additions & 0 deletions mythtv/libs/libmythtv/visualisations/goom/surf3d.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#include "surf3d.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void grid3d_free(grid3d **grid)
{
free ((*grid)->surf.vertex);
free ((*grid)->surf.svertex);
free (*grid);
*grid = NULL;
}

grid3d *grid3d_new (int sizex, int defx, int sizez, int defz, v3d center) {
int x = defx;
int y = defz;
grid3d *g = malloc (sizeof(grid3d));
surf3d *s = &(g->surf);
s->nbvertex = x*y;
s->vertex = malloc (x*y*sizeof(v3d));
s->svertex = malloc (x*y*sizeof(v3d));
s->center = center;

g->defx=defx;
g->sizex=sizex;
g->defz=defz;
g->sizez=sizez;
g->mode=0;

while (y) {
--y;
x = defx;
while (x) {
--x;
s->vertex[x+defx*y].x = (float)(x-defx/2)*sizex/defx;
s->vertex[x+defx*y].y = 0;
s->vertex[x+defx*y].z = (float)(y-defz/2)*sizez/defz;
}
}
return g;
}

//#undef HAVE_MMX
#include "drawmethods.h"

void surf3d_draw (surf3d *s, int color, int dist, int *buf, int *back, int W,int H) {
int i;
int *p1;
int *p2;
v2d v2;

for (i=0;i<s->nbvertex;i++) {
V3D_TO_V2D(s->svertex[i],v2,W,H,dist);
p1 = buf + v2.x + (v2.y*W);
p2 = back + v2.x + (v2.y*W);
if ((v2.x>=0) && (v2.y>=0) && (v2.x<W) && (v2.y<H)) {
*p1 = color;
}
}

/* Squelch a gcc warning */
(void)p2;
}

void grid3d_draw (grid3d *g, int color, int colorlow,
int dist, int *buf, int *back, int W,int H) {
int x;
// int *p1;
// int *p2;
v2d v2,v2x;

for (x=0;x<g->defx;x++) {
int z;
V3D_TO_V2D(g->surf.svertex[x],v2x,W,H,dist);

for (z=1;z<g->defz;z++) {
V3D_TO_V2D(g->surf.svertex[z*g->defx + x],v2,W,H,dist);
if (((v2.x != -666) || (v2.y!=-666))
&& ((v2x.x != -666) || (v2x.y!=-666))) {
draw_line(buf,v2x.x,v2x.y,v2.x,v2.y, colorlow, W, H);
draw_line(back,v2x.x,v2x.y,v2.x,v2.y, color, W, H);
DRAWMETHOD_DONE();
}
v2x = v2;
}
}
}

void surf3d_rotate (surf3d *s, float angle) {
int i;
float cosa;
float sina;
SINCOS(angle,sina,cosa);
for (i=0;i<s->nbvertex;i++) {
Y_ROTATE_V3D(s->vertex[i],s->svertex[i],cosa,sina);
}
}

void surf3d_translate (surf3d *s) {
int i;
for (i=0;i<s->nbvertex;i++) {
TRANSLATE_V3D(s->center,s->svertex[i]);
}
}

void grid3d_update (grid3d *g, float angle, float *vals, float dist) {
int i;
float cosa;
float sina;
surf3d *s = &(g->surf);
v3d cam = s->center;
cam.z += dist;

SINCOS((angle/4.3f),sina,cosa);
cam.y += sina*2.0f;
SINCOS(angle,sina,cosa);

if (g->mode==0) {
if (vals)
for (i=0;i<g->defx;i++)
s->vertex[i].y = s->vertex[i].y*0.2 + vals[i]*0.8;

for (i=g->defx;i<s->nbvertex;i++) {
s->vertex[i].y *= 0.255f;
s->vertex[i].y += (s->vertex[i-g->defx].y * 0.777f);
}
}

for (i=0;i<s->nbvertex;i++) {
Y_ROTATE_V3D(s->vertex[i],s->svertex[i],cosa,sina);
TRANSLATE_V3D(cam,s->svertex[i]);
}
}
37 changes: 37 additions & 0 deletions mythtv/libs/libmythtv/visualisations/goom/surf3d.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#ifndef _SURF3D_H
#define _SURF3D_H

#include "v3d.h"

typedef struct {
v3d *vertex;
v3d *svertex;
int nbvertex;

v3d center;
} surf3d;

typedef struct {
surf3d surf;

int defx;
int sizex;
int defz;
int sizez;
int mode;
} grid3d;

/* hi-level */

/* works on grid3d */
grid3d *grid3d_new (int sizex, int defx, int sizez, int defz, v3d center);
void grid3d_free(grid3d **grid);
void grid3d_update (grid3d *s, float angle, float *vals, float dist);

/* low level */
void surf3d_draw (surf3d *s, int color, int dist, int *buf, int *back, int W,int H);
void grid3d_draw (grid3d *g, int color, int colorlow, int dist, int *buf, int *back, int W,int H);
void surf3d_rotate (surf3d *s, float angle);
void surf3d_translate (surf3d *s);

#endif
19 changes: 19 additions & 0 deletions mythtv/libs/libmythtv/visualisations/goom/surface.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include "surface.h"
#include <stdlib.h>
#include <inttypes.h> // added for amd64 support

Surface * surface_new (int w, int h) {
Surface * s = (Surface*)malloc(sizeof(Surface));
s->realstart = (int*)malloc(w*h*4 + 128);
s->buf = (int*)((uintptr_t)s->realstart + 128 - (((uintptr_t)s->realstart) % 128));
s->size = w*h;
s->width = w;
s->height = h;
return s;
}

void surface_delete (Surface **s) {
free ((*s)->realstart);
free (*s);
*s = NULL;
}
16 changes: 16 additions & 0 deletions mythtv/libs/libmythtv/visualisations/goom/surface.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#ifndef _SURFACE_H
#define _SURFACE_H

typedef struct {
int * buf;
int width;
int height;
int size;

int * realstart;
} Surface;

Surface * surface_new (int w, int h) ;
void surface_delete (Surface **s) ;

#endif
223 changes: 223 additions & 0 deletions mythtv/libs/libmythtv/visualisations/goom/tentacle3d.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
#include <stdlib.h>

#include "v3d.h"
#include "surf3d.h"
#include "goom_tools.h"
#include "goomconfig.h"

#define D 256.0f

#define nbgrid 6
#define definitionx 15
#define definitionz 45

static float cycle = 0.0f;
static grid3d *grille[nbgrid];
static float *vals;

/* Prototypes to keep gcc from spewing warnings */
void tentacle_free (void);
void tentacle_new (void);
void tentacle_update(int *buf, int *back, int W, int H, short data[2][512], float rapport, int drawit);

void tentacle_free (void) {
int tmp;
free (vals);
for (tmp=0;tmp<nbgrid;tmp++) {
grid3d_free(&(grille[tmp]));
}
}

void tentacle_new (void) {
int tmp;

v3d center = {0,-17.0,0};
vals = malloc ((definitionx+20)*sizeof(float));

for (tmp=0;tmp<nbgrid;tmp++) {
int x,z;
z = 45+rand()%30;
x = 85+rand()%5;
center.z = z;
grille[tmp] = grid3d_new (x,definitionx,z,definitionz+rand()%10,center);
center.y += 8;
}
}

static inline unsigned char
lighten (unsigned char value, float power)
{
int val = value;
float t = (float) val * log10(power) / 2.0;

if (t > 0) {
val = (int) t; // (32.0f * log (t));
if (val > 255)
val = 255;
if (val < 0)
val = 0;
return val;
}
else {
return 0;
}
}

static void
lightencolor (int *col, float power)
{
unsigned char *color;

color = (unsigned char *) col;
*color = lighten (*color, power);
color++;
*color = lighten (*color, power);
color++;
*color = lighten (*color, power);
color++;
*color = lighten (*color, power);
}

// retourne x>>s , en testant le signe de x
#define ShiftRight(_x,_s) ((_x<0) ? -(-_x>>_s) : (_x>>_s))

static
int evolutecolor (unsigned int src,unsigned int dest, unsigned int mask, unsigned int incr) {
int color = src & (~mask);
src &= mask;
dest &= mask;

if ((src!=mask)
&&(src<dest))
src += incr;

if (src>dest)
src -= incr;
return (src&mask)|color;
}

static void pretty_move (float cycle, float *dist,float *dist2, float *rotangle) {
static float distt = 10.0f;
static float distt2 = 0.0f;
static float rot = 0.0f; // entre 0 et 2 * M_PI
static int happens = 0;
float tmp;
static int rotation = 0;
static int lock = 0;

if (happens)
happens -= 1;
else if (lock == 0) {
happens = iRAND(200)?0:100+iRAND(60);
lock = happens * 3 / 2;
}
else lock --;
// happens = 1;

tmp = happens?8.0f:0;
*dist2 = distt2 = (tmp + 15.0f*distt2)/16.0f;

tmp = 30+D-90.0f*(1.0f+sin(cycle*19/20));
if (happens)
tmp *= 0.6f;

*dist = distt = (tmp + 3.0f*distt)/4.0f;

if (!happens){
tmp = M_PI*sin(cycle)/32+3*M_PI/2;
}
else {
rotation = iRAND(500)?rotation:iRAND(2);
if (rotation)
cycle *= 2.0f*M_PI;
else
cycle *= -1.0f*M_PI;
tmp = cycle - (M_PI*2.0) * floor(cycle/(M_PI*2.0));
}

if (abs(tmp-rot) > abs(tmp-(rot+2.0*M_PI))) {
rot = (tmp + 15.0f*(rot+2*M_PI)) / 16.0f;
if (rot>2.0*M_PI)
rot -= 2.0*M_PI;
*rotangle = rot;
}
else if (abs(tmp-rot) > abs(tmp-(rot-2.0*M_PI))) {
rot = (tmp + 15.0f*(rot-2.0*M_PI)) / 16.0f;
if (rot<0.0f)
rot += 2.0*M_PI;
*rotangle = rot;
}
else
*rotangle = rot = (tmp + 15.0f*rot) / 16.0f;
}

void tentacle_update(int *buf, int *back, int W, int H, short data[2][512], float rapport, int drawit) {
int tmp;
int tmp2;

static int colors[] = {
(0x18<<(ROUGE*8))|(0x4c<<(VERT*8))|(0x2f<<(BLEU*8)),
(0x48<<(ROUGE*8))|(0x2c<<(VERT*8))|(0x6f<<(BLEU*8)),
(0x58<<(ROUGE*8))|(0x3c<<(VERT*8))|(0x0f<<(BLEU*8))};

static int col = (0x28<<(ROUGE*8))|(0x2c<<(VERT*8))|(0x5f<<(BLEU*8));
static int dstcol = 0;
static float lig = 1.15f;
static float ligs = 0.1f;

int color;
int colorlow;

float dist,dist2,rotangle;

if ((!drawit) && (ligs>0.0f))
ligs = -ligs;

lig += ligs;

if (lig > 1.01f) {
if ((lig>10.0f) | (lig<1.1f)) ligs = -ligs;

if ((lig<6.3f)&&(iRAND(30)==0))
dstcol=iRAND(3);

col = evolutecolor(col,colors[dstcol],0xff,0x01);
col = evolutecolor(col,colors[dstcol],0xff00,0x0100);
col = evolutecolor(col,colors[dstcol],0xff0000,0x010000);
col = evolutecolor(col,colors[dstcol],0xff000000,0x01000000);

color = col;
colorlow = col;

lightencolor(&color,lig * 2.0f + 2.0f);
lightencolor(&colorlow,(lig/3.0f)+0.67f);

rapport = 1.0f + 2.0f * (rapport - 1.0f);
rapport *= 1.2f;
if (rapport > 1.12f)
rapport = 1.12f;

pretty_move (cycle,&dist,&dist2,&rotangle);

for (tmp=0;tmp<nbgrid;tmp++) {
for (tmp2=0;tmp2<definitionx;tmp2++) {
float val = (float)(ShiftRight(data[0][iRAND(511)],10)) * rapport;
vals[tmp2] = val;
}

grid3d_update (grille[tmp],rotangle, vals, dist2);
}
cycle+=0.01f;
for (tmp=0;tmp<nbgrid;tmp++)
grid3d_draw (grille[tmp],color,colorlow,dist,buf,back,W,H);
}
else {
lig = 1.05f;
if (ligs < 0.0f)
ligs = -ligs;
pretty_move (cycle,&dist,&dist2,&rotangle);
cycle+=0.1f;
if (cycle > 1000)
cycle = 0;
}
}
8 changes: 8 additions & 0 deletions mythtv/libs/libmythtv/visualisations/goom/tentacle3d.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef _TENTACLE3D_H
#define _TENTACLE3D_H

void tentacle_new (void);
void tentacle_update(int *buf, int *back, int W, int H, short[2][512], float, int drawit);
void tentacle_free (void);

#endif
59 changes: 59 additions & 0 deletions mythtv/libs/libmythtv/visualisations/goom/v3d.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#ifndef _V3D_H
#define _V3D_H

#include <math.h>
#include <stdlib.h>
#include <stdio.h>

#include "mathtools.h"

typedef struct {
float x,y,z;
} v3d;

typedef struct {
int x,y;
} v2d;

/*
* projete le vertex 3D sur le plan d'affichage
* retourne (0,0) si le point ne doit pas etre affiche.
*
* bonne valeur pour distance : 256
*/
#define V3D_TO_V2D(v3,v2,width,height,distance) \
{ \
int Xp, Yp; \
if (v3.z > 2) { \
F2I((distance * v3.x / v3.z),Xp) ; \
F2I((distance * v3.y / v3.z),Yp) ; \
v2.x = Xp + (width>>1); \
v2.y = -Yp + (height>>1); \
} \
else v2.x=v2.y=-666; \
}

/*
* rotation selon Y du v3d vi d'angle a (cosa=cos(a), sina=sin(a))
* centerz = centre de rotation en z
*/
#define Y_ROTATE_V3D(vi,vf,sina,cosa)\
{\
vf.x = vi.x * cosa - vi.z * sina;\
vf.z = vi.x * sina + vi.z * cosa;\
vf.y = vi.y;\
}

/*
* translation
*/
#define TRANSLATE_V3D(vsrc,vdest)\
{\
vdest.x += vsrc.x;\
vdest.y += vsrc.y;\
vdest.z += vsrc.z;\
}

#define MUL_V3D(lf,v) {v.x*=lf;v.y*=lf;v.z*=lf;}

#endif
158 changes: 158 additions & 0 deletions mythtv/libs/libmythtv/visualisations/goom/zoom_filter_mmx.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
/* Prototypes to keep gcc from spewing warnings */
void zoom_filter_mmx (int prevX, int prevY, unsigned int *expix1, unsigned int *expix2, int *brutS, int *brutD, int buffratio, int precalCoef[16][16]);
int zoom_filter_mmx_supported (void);

#ifdef MMX
#define BUFFPOINTNB 16
#define BUFFPOINTMASK 0xffff
#define BUFFINCR 0xff

#include "mmx.h"

#define sqrtperte 16
// faire : a % sqrtperte <=> a & pertemask
#define PERTEMASK 0xf
// faire : a / sqrtperte <=> a >> PERTEDEC
#define PERTEDEC 4

#include "libavutil/cpu.h"

int zoom_filter_mmx_supported () {
return (av_get_cpu_flags() & AV_CPU_FLAG_MMX);
}

void zoom_filter_mmx (int prevX, int prevY,
unsigned int *expix1, unsigned int *expix2,
int *brutS, int *brutD, int buffratio,
int precalCoef[16][16])
{
unsigned int ax = (prevX-1)<<PERTEDEC, ay = (prevY-1)<<PERTEDEC;

int bufsize = prevX * prevY;
int loop;

pxor_r2r(mm7,mm7);

for (loop=0; loop<bufsize; loop++)
{
int px,py;
int pos;
int coeffs;

int posplusprevX;

int myPos = loop << 1, myPos2 = myPos + 1;
int brutSmypos = brutS[myPos];

px = brutSmypos +
(((brutD[myPos] - brutSmypos)*buffratio) >> BUFFPOINTNB);

brutSmypos = brutS[myPos2];
py = brutSmypos +
(((brutD[myPos2] - brutSmypos)*buffratio) >> BUFFPOINTNB);

if (px < 0)
px = 0;

if (py < 0)
py = 0;

if ((py>=(int)ay) || (px>=(int)ax))
{
pos=coeffs=0;
}
else {
pos = ((px >> PERTEDEC) + prevX * (py >> PERTEDEC));
/* coef en modulo 15 */
coeffs = precalCoef [px & PERTEMASK][py & PERTEMASK];
}

posplusprevX = pos + prevX;

movd_m2r(coeffs, mm6);

/* recuperation des deux premiers pixels dans mm0 et mm1 */
movq_m2r(expix1[pos], mm0); /* b1-v1-r1-a1-b2-v2-r2-a2 */
movq_r2r(mm0, mm1); /* b1-v1-r1-a1-b2-v2-r2-a2 */

/* depackage du premier pixel */
punpcklbw_r2r(mm7, mm0); /* 00-b2-00-v2-00-r2-00-a2 */
movq_r2r(mm6, mm5); /* xx-xx-xx-xx-c4-c3-c2-c1 */

/* depackage du 2ieme pixel */
punpckhbw_r2r(mm7, mm1); /* 00-b1-00-v1-00-r1-00-a1 */

/* extraction des coefficients... */
punpcklbw_r2r(mm5, mm6); /* c4-c4-c3-c3-c2-c2-c1-c1 */
movq_r2r(mm6, mm4); /* c4-c4-c3-c3-c2-c2-c1-c1 */
movq_r2r(mm6, mm5); /* c4-c4-c3-c3-c2-c2-c1-c1 */
punpcklbw_r2r(mm5, mm6); /* c2-c2-c2-c2-c1-c1-c1-c1 */
punpckhbw_r2r(mm5, mm4); /* c4-c4-c4-c4-c3-c3-c3-c3 */

movq_r2r(mm6, mm3); /* c2-c2-c2-c2-c1-c1-c1-c1 */
punpcklbw_r2r(mm7, mm6); /* 00-c1-00-c1-00-c1-00-c1 */
punpckhbw_r2r(mm7, mm3); /* 00-c2-00-c2-00-c2-00-c2 */

/* multiplication des pixels par les coefficients */
pmullw_r2r(mm6, mm0); /* c1*b2-c1*v2-c1*r2-c1*a2 */
pmullw_r2r(mm3, mm1); /* c2*b1-c2*v1-c2*r1-c2*a1 */
paddw_r2r(mm1, mm0);

/* ...extraction des 2 derniers coefficients */
movq_r2r(mm4, mm5); /* c4-c4-c4-c4-c3-c3-c3-c3 */
punpcklbw_r2r(mm7, mm4); /* 00-c3-00-c3-00-c3-00-c3 */
punpckhbw_r2r(mm7, mm5); /* 00-c4-00-c4-00-c4-00-c4 */

/* ajouter la longueur de ligne a esi */
/* recuperation des 2 derniers pixels */
movq_m2r(expix1[posplusprevX], mm1);
movq_r2r(mm1, mm2);

/* depackage des pixels */
punpcklbw_r2r(mm7, mm1);
punpckhbw_r2r(mm7, mm2);

/* multiplication pas les coeffs */
pmullw_r2r(mm4, mm1);
pmullw_r2r(mm5, mm2);

/* ajout des valeurs obtenues de iso8859-15 à la valeur finale */
paddw_r2r(mm1, mm0);
paddw_r2r(mm2, mm0);

/* division par 256 = 16+16+16+16, puis repackage du pixel final */
psrlw_i2r(8, mm0);
packuswb_r2r(mm7, mm0);
movd_r2m(mm0,expix2[loop]);
}
emms();
}

#else

int zoom_filter_mmx_supported () {
return 0;
}

void zoom_filter_mmx (int prevX, int prevY,
unsigned int *expix1, unsigned int *expix2,
int *brutS, int *brutD, int buffratio,
int precalCoef[16][16])
{
(void)prevX;
(void)prevY;
(void)expix1;
(void)expix2;
(void)brutS;
(void)brutD;
(void)buffratio;
(void)precalCoef;
return;
}

#endif

/*
* vim:ts=4:sw=4:ai:et:si:sts=4
*/

267 changes: 267 additions & 0 deletions mythtv/libs/libmythtv/visualisations/goom/zoom_filter_xmmx.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,267 @@
#include <mythtv/mythconfig.h>

/* Prototypes to keep gcc from spewing warnings */
void zoom_filter_xmmx (int prevX, int prevY, unsigned int *expix1, unsigned int *expix2, int *brutS, int *brutD, int buffratio, int precalCoef[16][16]);
int zoom_filter_xmmx_supported (void);


#if defined(MMX) && !defined(ARCH_X86_64)
/* a definir pour avoir exactement le meme resultat que la fonction C
* (un chouillat plus lent)
*/
#define STRICT_COMPAT
//#define HAVE_ATHLON

#define BUFFPOINTNB 16
#define BUFFPOINTMASK 0xffff
#define BUFFINCR 0xff

#define sqrtperte 16
// faire : a % sqrtperte <=> a & pertemask
#define PERTEMASK 0xf
// faire : a / sqrtperte <=> a >> PERTEDEC
#define PERTEDEC 4


//#define MMX_TRACE
#include "mmx.h"

int zoom_filter_xmmx_supported () {
return (mm_support()&0x8)>>3;
}

void zoom_filter_xmmx (int prevX, int prevY,
unsigned int *expix1, unsigned int *expix2,
int *lbruS, int *lbruD, int buffratio,
int precalCoef[16][16])
{
int bufsize = prevX * prevY; /* taille du buffer */
volatile int loop; /* variable de boucle */

mmx_t *brutS = (mmx_t*)lbruS; /* buffer de transformation source */
mmx_t *brutD = (mmx_t*)lbruD; /* buffer de transformation dest */

volatile mmx_t prevXY;
volatile mmx_t ratiox;
//volatile mmx_t interpix;

expix1[0]=expix1[prevX-1]=expix1[prevX*prevY-1]=expix1[prevX*prevY-prevX]=0;

prevXY.ud[0] = (prevX-1)<<PERTEDEC;
prevXY.ud[1] = (prevY-1)<<PERTEDEC;

ratiox.d[0] = buffratio;
ratiox.d[1] = buffratio;
movq_m2r (ratiox, mm6);
pslld_i2r (16,mm6);

pxor_r2r (mm7,mm7); /* mise a zero de mm7 */

loop=0;

/*
* NOTE : mm6 et mm7 ne sont pas modifies dans la boucle.
*/
while (loop < bufsize)
{
/*
* pre : mm6 = [buffratio<<16|buffratio<<16]
* post : mm0 = S + ((D-S)*buffratio)>>16 format [X|Y]
* modified = mm0,mm1,mm2
*/

__asm__ __volatile__ (
"movq %0,%%mm0\n"
"movq %1,%%mm1\n"
: :"m"(brutS[loop]),"m"(brutD[loop])
); /* mm0 = S */

psubd_r2r (mm0,mm1); /* mm1 = D - S */
movq_r2r (mm1, mm2); /* mm2 = D - S */

pslld_i2r (16,mm1);
mmx_r2r (pmulhuw, mm6, mm1); /* mm1 = ?? */
pmullw_r2r (mm6, mm2);

paddd_r2r (mm2, mm1); /* mm1 = (D - S) * buffratio >> 16 */
pslld_i2r (16,mm0);

paddd_r2r (mm1, mm0); /* mm0 = S + mm1 */
psrld_i2r (16, mm0);

/*
* pre : mm0 : position vector on screen
* prevXY : coordinate of the lower-right point on screen
* post : clipped mm0
* modified : mm0,mm1,mm2
*/
movq_m2r (prevXY,mm1);
pcmpgtd_r2r (mm0, mm1); /* mm0 en X contient :
1111 si prevXY > px
0000 si prevXY <= px
(idem pour y) */
#ifdef STRICT_COMPAT
movq_r2r (mm1,mm2);
punpckhdq_r2r (mm2,mm2);
punpckldq_r2r (mm1,mm1);
pand_r2r (mm2, mm0);
#endif
pand_r2r (mm1, mm0); /* on met a zero la partie qui deborde */

/*
* pre : mm0 : clipped position on screen
*
* post : mm3 & mm4 : coefs for this position
* mm1 : X vector [0|X]
*
* modif : eax,ecx
*/
__asm__ __volatile__ (
"movd %%mm0,%%ecx\n"
"movq %%mm0,%%mm1\n"

"andl $15,%%ecx\n"
"psrlq $32,%%mm1\n"

"shll $6,%%ecx\n"
"movd %%mm1,%%eax\n"

"addl %0,%%ecx\n"
"andl $15,%%eax\n"

"movd (%%ecx,%%eax,4),%%mm3\n"
/* ::"X"(precalCoef):"eax","ecx"); */
::"m"(precalCoef):"eax","ecx");


/*
* extraction des coefficients...
*
* pre : coef dans mm3
*
* post : coef extraits dans mm3 (c1 & c2)
* et mm4 (c3 & c4)
*
* modif : mm5
*/
// entrelace avec portion d'apres (cf les '^')
// movq_r2r (mm3, mm5); /* ??-??-??-??-c4-c3-c2-c1 */
// punpcklbw_r2r (mm5, mm3); /* c4-c4-c3-c3-c2-c2-c1-c1 */
// movq_r2r (mm3, mm4); /* c4-c4-c3-c3-c2-c2-c1-c1 */
// movq_r2r (mm3, mm5); /* c4-c4-c3-c3-c2-c2-c1-c1 */

// punpcklbw_r2r (mm5, mm3); /* c2-c2-c2-c2-c1-c1-c1-c1 */
// punpckhbw_r2r (mm5, mm4); /* c4-c4-c4-c4-c3-c3-c3-c3 */

/*
* pre : mm0 : Y pos [*|Y]
* mm1 : X pos [*|X]
*
* post : mm0 : expix1[position]
* mm2 : expix1[position+largeur]
*
* modif : eax,ecx
*/
psrld_i2r (PERTEDEC,mm0);
psrld_i2r (PERTEDEC,mm1);
__asm__ __volatile__ (
"movd %%mm1,%%eax\n"
/*^*/ "movq %%mm3,%%mm5\n" /*^*/

"mull %1\n"
"movd %%mm0,%%ecx\n"
/*^*/ "punpcklbw %%mm5, %%mm3\n" /*^*/

"addl %%ecx,%%eax\n"
/*^*/ "movq %%mm3,%%mm4\n" /*^*/
/*^*/ "movq %%mm3,%%mm5\n" /*^*/

"movl %0,%%ecx\n"
/*^*/ "punpcklbw %%mm5,%%mm3\n" /*^*/

"movq (%%ecx,%%eax,4),%%mm0\n"
/*^*/ "punpckhbw %%mm5,%%mm4\n" /*^*/

"addl %1,%%eax\n"
"movq (%%ecx,%%eax,4),%%mm2\n"

: : "X"(expix1), "X"(prevX):"eax","ecx"
);

/*
* pre : mm0 : expix1[position]
* mm2 : expix1[position+largeur]
* mm3 & mm4 : coefs
*/

/* recopie des deux premiers pixels dans mm0 et mm1 */
movq_r2r (mm0, mm1); /* b1-v1-r1-a1-b2-v2-r2-a2 */

/* depackage du premier pixel */
punpcklbw_r2r (mm7, mm0); /* 00-b2-00-v2-00-r2-00-a2 */

/* extraction des coefficients... */

movq_r2r (mm3, mm5); /* c2-c2-c2-c2-c1-c1-c1-c1 */

/*^en parrallele^*/ /* depackage du 2ieme pixel */
/*^*/ punpckhbw_r2r (mm7, mm1); /* 00-b1-00-v1-00-r1-00-a1 */

punpcklbw_r2r (mm7, mm5); /* 00-c1-00-c1-00-c1-00-c1 */
punpckhbw_r2r (mm7, mm3); /* 00-c2-00-c2-00-c2-00-c2 */

/* multiplication des pixels par les coefficients */
pmullw_r2r (mm5, mm0); /* c1*b2-c1*v2-c1*r2-c1*a2 */
pmullw_r2r (mm3, mm1); /* c2*b1-c2*v1-c2*r1-c2*a1 */
paddw_r2r (mm1, mm0);

/* ...extraction des 2 derniers coefficients */
movq_r2r (mm4, mm5); /* c4-c4-c4-c4-c3-c3-c3-c3 */
punpcklbw_r2r (mm7, mm4); /* 00-c3-00-c3-00-c3-00-c3 */
punpckhbw_r2r (mm7, mm5); /* 00-c4-00-c4-00-c4-00-c4 */

/* recuperation des 2 derniers pixels */
movq_r2r (mm2, mm1);

/* depackage des pixels */
punpcklbw_r2r (mm7, mm1);
punpckhbw_r2r (mm7, mm2);

/* multiplication pas les coeffs */
pmullw_r2r (mm4, mm1);
pmullw_r2r (mm5, mm2);

/* ajout des valeurs obtenues à la valeur finale */
paddw_r2r (mm1, mm0);
paddw_r2r (mm2, mm0);

/* division par 256 = 16+16+16+16, puis repackage du pixel final */
psrlw_i2r (8, mm0);
packuswb_r2r (mm7, mm0);

movd_r2m (mm0,expix2[loop]);

++loop;
}
#ifdef HAVE_ATHLON
__asm__ __volatile__ ("femms\n");
#else
emms();
#endif
}
#else
int zoom_filter_xmmx_supported () {
return 0;
}
void zoom_filter_xmmx (int prevX, int prevY,
unsigned int *expix1, unsigned int *expix2,
int *lbruS, int *lbruD, int buffratio,
int precalCoef[16][16])
{
(void) prevX; (void) prevY;
(void) expix1; (void) expix2;
(void) lbruS; (void) lbruD;
(void) buffratio; (void) precalCoef;
return;
}
#endif
158 changes: 158 additions & 0 deletions mythtv/libs/libmythtv/visualisations/videovisualgoom.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
#include "mythlogging.h"

#include "mythmainwindow.h"
#ifdef USING_OPENGL
#include "mythrender_opengl.h"
#endif

extern "C" {
#include "goom/goom_tools.h"
#include "goom/goom_core.h"
}

#include "videovisualgoom.h"

VideoVisualGoom::VideoVisualGoom(AudioPlayer *audio, MythRender *render, bool hd)
: VideoVisual(audio, render), m_buffer(NULL), m_surface(NULL), m_hd(hd)
{
int max_width = m_hd ? 1200 : 600;
int max_height = m_hd ? 800 : 400;
MythMainWindow *mw = GetMythMainWindow();
QSize sz = mw ? mw->GetUIScreenRect().size() : QSize(600, 400);
int width = (sz.width() > max_width) ? max_width : sz.width();
int height = (sz.height() > max_height) ? max_height : sz.height();
m_area = QRect(0, 0, width, height);
goom_init(width, height, 0);
LOG(VB_GENERAL, LOG_INFO, QString("Initialised Goom (%1x%2)")
.arg(width).arg(height));
}

VideoVisualGoom::~VideoVisualGoom()
{
#ifdef USING_OPENGL
if (m_surface && m_render &&
(m_render->Type() == kRenderOpenGL1 ||
m_render->Type() == kRenderOpenGL2 ||
m_render->Type() == kRenderOpenGL2ES))
{
MythRenderOpenGL *glrender =
static_cast<MythRenderOpenGL*>(m_render);
if (glrender)
glrender->DeleteTexture(m_surface);
m_surface = 0;
}
#endif

goom_close();
}

void VideoVisualGoom::Draw(const QRect &area, MythPainter *painter,
QPaintDevice *device)
{
if (m_disabled || !m_render || area.isEmpty())
return;

QMutexLocker lock(mutex());
unsigned int* last = m_buffer;
VisualNode *node = GetNode();
if (node)
{
int numSamps = 512;
if (node->length < 512)
numSamps = node->length;

signed short int data[2][512];
int i= 0;
for (; i < numSamps; i++)
{
data[0][i] = node->left[i];
data[1][i] = node->right ? node->right[i] : data[0][i];
}

for (; i < 512; i++)
{
data[0][i] = 0;
data[1][i] = 0;
}

m_buffer = goom_update(data, 0);
}

#ifdef USING_OPENGL
if ((m_render->Type() == kRenderOpenGL1) ||
(m_render->Type() == kRenderOpenGL2) ||
(m_render->Type() == kRenderOpenGL2ES))
{
MythRenderOpenGL *glrender =
static_cast<MythRenderOpenGL*>(m_render);
if (!m_surface && glrender && m_buffer)
{
m_surface = glrender->CreateTexture(m_area.size(),
glrender->GetFeatures() & kGLExtPBufObj, 0,
GL_UNSIGNED_BYTE, GL_RGBA, GL_RGBA8,
GL_LINEAR_MIPMAP_LINEAR);
}

if (m_surface && glrender && m_buffer)
{
if (m_buffer != last)
{
bool copy = glrender->GetFeatures() & kGLExtPBufObj;
void* buf = glrender->GetTextureBuffer(m_surface, copy);
if (copy)
memcpy(buf, m_buffer, m_area.width() * m_area.height() * 4);
glrender->UpdateTexture(m_surface, (void*)m_buffer);
}
QRectF src(m_area);
QRectF dst(area);
glrender->DrawBitmap(&m_surface, 1, 0, &src, &dst, 0);
}
}
#endif
}

static class VideoVisualGoomFactory : public VideoVisualFactory
{
public:
const QString &name(void) const
{
static QString name("Goom");
return name;
}

VideoVisual *Create(AudioPlayer *audio,
MythRender *render) const
{
return new VideoVisualGoom(audio, render, false);
}

virtual bool SupportedRenderer(RenderType type)
{
return (type == kRenderOpenGL1 ||
type == kRenderOpenGL2 ||
type == kRenderOpenGL2ES);
}
} VideoVisualGoomFactory;

static class VideoVisualGoomHDFactory : public VideoVisualFactory
{
public:
const QString &name(void) const
{
static QString name("Goom HD");
return name;
}

VideoVisual *Create(AudioPlayer *audio,
MythRender *render) const
{
return new VideoVisualGoom(audio, render, true);
}

virtual bool SupportedRenderer(RenderType type)
{
return (type == kRenderOpenGL1 ||
type == kRenderOpenGL2 ||
type == kRenderOpenGL2ES);
}
} VideoVisualGoomHDFactory;
22 changes: 22 additions & 0 deletions mythtv/libs/libmythtv/visualisations/videovisualgoom.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#ifndef VIDEOVISUALGOOM_H
#define VIDEOVISUALGOOM_H

#include "videovisual.h"

class VideoVisualGoom : public VideoVisual
{
public:
VideoVisualGoom(AudioPlayer *audio, MythRender *render, bool hd);
virtual ~VideoVisualGoom();

virtual void Draw(const QRect &area, MythPainter *painter,
QPaintDevice* device);
virtual QString Name(void) { return m_hd ? "Goom HD" : "Goom"; }

private:
unsigned int* m_buffer;
uint m_surface;
bool m_hd;
};

#endif // VIDEOVISUALGOOM_H