winamp/Src/Plugins/Visualization/vis_avs/r_defs.h
2024-09-24 14:54:57 +02:00

740 lines
16 KiB
C++

/*
LICENSE
-------
Copyright 2005 Nullsoft, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of Nullsoft nor the names of its contributors may be used to
endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _R_DEFS_H_
#define _R_DEFS_H_
// base class declaration, compatibility class
class RString;
class C_RBASE {
public:
C_RBASE() { }
virtual ~C_RBASE() { };
virtual int render(char visdata[2][2][576], int isBeat, int *framebuffer, int *fbout, int w, int h)=0; // returns 1 if fbout has dest
virtual HWND conf(HINSTANCE hInstance, HWND hwndParent){return 0;};
virtual char *get_desc()=0;
virtual void load_config(unsigned char *data, int len) { }
virtual int save_config(unsigned char *data) { return 0; }
void load_string(RString &s,unsigned char *data, int &pos, int len);
void save_string(unsigned char *data, int &pos, RString &text);
};
class C_RBASE2 : public C_RBASE {
public:
C_RBASE2() { }
virtual ~C_RBASE2() { };
int getRenderVer2() { return 2; }
virtual int smp_getflags() { return 0; } // return 1 to enable smp support
// returns # of threads you desire, <= max_threads, or 0 to not do anything
// default should return max_threads if you are flexible
virtual int smp_begin(int max_threads, char visdata[2][2][576], int isBeat, int *framebuffer, int *fbout, int w, int h) { return 0; }
virtual void smp_render(int this_thread, int max_threads, char visdata[2][2][576], int isBeat, int *framebuffer, int *fbout, int w, int h) { };
virtual int smp_finish(char visdata[2][2][576], int isBeat, int *framebuffer, int *fbout, int w, int h) { return 0; }; // return value is that of render() for fbstuff etc
};
// defined in main.cpp, render.cpp
extern char g_path[];
extern unsigned char g_blendtable[256][256];
extern int g_reset_vars_on_recompile;
// use this function to get a global buffer, and the last flag says whether or not to
// allocate it if it's not valid...
#define NBUF 8
void *getGlobalBuffer(int w, int h, int n, int do_alloc);
// implemented in util.cpp
char* GetTextResource(UINT id);
void GR_SelectColor(HWND hwnd, int *a);
void GR_DrawColoredButton(DRAWITEMSTRUCT *di, COLORREF color);
void loadComboBox(HWND dlg, char *ext, char *selectedName);
void compilerfunctionlist(HWND hwndDlg, char *localinfo=NULL);
// matrix.cpp
void matrixRotate(float matrix[], char m, float Deg);
void matrixTranslate(float m[], float x, float y, float z);
void matrixMultiply(float *dest, float src[]);
void matrixApply(float *m, float x, float y, float z, float *outx, float *outy, float *outz);
// linedraw.cpp
extern int g_line_blend_mode;
void line(int *fb, int x1,int y1,int x2,int y2, int width, int height, int color, int lw);
// inlines
static unsigned int __inline BLEND(unsigned int a, unsigned int b)
{
register unsigned int r,t;
r=(a&0xff)+(b&0xff);
t=min(r,0xff);
r=(a&0xff00)+(b&0xff00);
t|=min(r,0xff00);
r=(a&0xff0000)+(b&0xff0000);
t|=min(r,0xff0000);
r=(a&0xff000000)+(b&0xff000000);
return t|min(r,0xff000000);
}
#if 1
#define FASTMAX(x,y) max(x,y)
// (x-(((x-y)>>(32-1))&(x-y))) // hmm not faster :(
#define FASTMIN(x,y) min(x,y)
//(x+(((y-x)>>(32-1))&(y-x)))
#else
#pragma warning( push, 1 )
static __inline int FASTMAX(int x, int y)
{
__asm
{
mov ecx, [x]
mov eax, [y]
sub ecx, eax
cmc
and ecx, edx
add eax, ecx
}
}
static __inline int FASTMIN(int x, int y)
{
__asm
{
mov ecx, [x]
mov eax, [y]
sub ecx, eax
sbb edx, edx
and ecx, edx
add eax, ecx
}
}
#pragma warning( pop )
#endif
static unsigned int __inline BLEND_MAX(unsigned int a, unsigned int b)
{
register unsigned int t;
int _a=a&0xff;
int _b=b&0xff;
t=FASTMAX(_a,_b);
_a=a&0xff00; _b=b&0xff00;
t|=FASTMAX(_a,_b);
_a=a&0xff0000; _b=b&0xff0000;
t|=FASTMAX(_a,_b);
return t;
}
static unsigned int __inline BLEND_MIN(unsigned int a, unsigned int b)
{
#if 1
register unsigned int t;
int _a=a&0xff;
int _b=b&0xff;
t=FASTMIN(_a,_b);
_a=a&0xff00; _b=b&0xff00;
t|=FASTMIN(_a,_b);
_a=a&0xff0000; _b=b&0xff0000;
t|=FASTMIN(_a,_b);
return t;
#else
__asm
{
mov ecx, [a]
mov eax, [b]
and ecx, 0xff
and eax, 0xff
mov esi, [a]
mov ebx, [b]
sub ecx, eax
sbb edx, edx
and esi, 0xff00
and ebx, 0xff00
and ecx, edx
sub esi, ebx
sbb edx, edx
add eax, ecx
and esi, edx
mov ecx, [a]
add ebx, esi
and ecx, 0xff0000
mov esi, [b]
or eax, ebx
and esi, 0xff0000
sub ecx, esi
sbb edx, edx
and ecx, edx
add esi, ecx
or eax, esi
}
#endif
}
#ifdef FASTMAX
#undef FASTMAX
#undef FASTMIN
#endif
static unsigned int __inline BLEND_AVG(unsigned int a, unsigned int b)
{
return ((a>>1)&~((1<<7)|(1<<15)|(1<<23)))+((b>>1)&~((1<<7)|(1<<15)|(1<<23)));
}
static unsigned int __inline BLEND_SUB(unsigned int a, unsigned int b)
{
register int r,t;
r=(a&0xff)-(b&0xff);
t=max(r,0);
r=(a&0xff00)-(b&0xff00);
t|=max(r,0);
r=(a&0xff0000)-(b&0xff0000);
t|=max(r,0);
r=(a&0xff000000)-(b&0xff000000);
return t|max(r,0);
}
#ifdef NO_MMX
#define BLEND_ADJ BLEND_ADJ_NOMMX
#endif
static unsigned int __inline BLEND_ADJ_NOMMX(unsigned int a, unsigned int b, int v)
{
register int t;
t=g_blendtable[a&0xFF][v]+g_blendtable[b&0xFF][0xFF-v];
t|=(g_blendtable[(a&0xFF00)>>8][v]+g_blendtable[(b&0xFF00)>>8][0xFF-v])<<8;
t|=(g_blendtable[(a&0xFF0000)>>16][v]+g_blendtable[(b&0xFF0000)>>16][0xFF-v])<<16;
return t;
}
static unsigned int __inline BLEND_MUL(unsigned int a, unsigned int b)
{
register int t;
t=g_blendtable[a&0xFF][b&0xFF];
t|=g_blendtable[(a&0xFF00)>>8][(b&0xFF00)>>8]<<8;
t|=g_blendtable[(a&0xFF0000)>>16][(b&0xFF0000)>>16]<<16;
return t;
}
static __inline void BLEND_LINE(int *fb, int color)
{
register int bm=g_line_blend_mode&0xff;
switch (g_line_blend_mode&0xff)
{
case 1: *fb=BLEND(*fb,color); break;
case 2: *fb=BLEND_MAX(*fb,color); break;
case 3: *fb=BLEND_AVG(*fb,color); break;
case 4: *fb=BLEND_SUB(*fb,color); break;
case 5: *fb=BLEND_SUB(color,*fb); break;
case 6: *fb=BLEND_MUL(*fb,color); break;
case 7: *fb=BLEND_ADJ_NOMMX(*fb,color,(g_line_blend_mode>>8)&0xff); break;
case 8: *fb=*fb^color; break;
case 9: *fb=BLEND_MIN(*fb,color); break;
default: *fb=color; break;
}
}
extern unsigned int const mmx_blend4_revn[2];
extern int const mmx_blend4_zero;
extern int const mmx_blendadj_mask[2];
// NOTE. WHEN USING THIS FUNCTION, BE SURE TO DO 'if (g_mmx_available) __asm emms;' before calling
// any fpu code, or before returning.
#pragma warning( push, 1 )
#ifndef NO_MMX
static unsigned int __inline BLEND_ADJ(unsigned int a, unsigned int b, int v)
{
__asm
{
movd mm3, [v] // VVVVVVVV
movd mm0, [a]
packuswb mm3, mm3 // 0000HHVV
movd mm1, [b]
punpcklwd mm3, mm3 // HHVVHHVV
movq mm4, [mmx_blend4_revn]
punpckldq mm3, mm3 // HHVVHHVV HHVVHHVV
punpcklbw mm0, [mmx_blend4_zero]
pand mm3, [mmx_blendadj_mask]
punpcklbw mm1, [mmx_blend4_zero]
psubw mm4, mm3
pmullw mm0, mm3
pmullw mm1, mm4
paddw mm0, mm1
psrlw mm0, 8
packuswb mm0, mm0
movd eax, mm0
}
}
#endif
static __inline unsigned int BLEND4(unsigned int *p1, unsigned int w, int xp, int yp)
{
#ifdef NO_MMX
register int t;
unsigned char a1,a2,a3,a4;
a1=g_blendtable[255-xp][255-yp];
a2=g_blendtable[xp][255-yp];
a3=g_blendtable[255-xp][yp];
a4=g_blendtable[xp][yp];
t=g_blendtable[p1[0]&0xff][a1]+g_blendtable[p1[1]&0xff][a2]+g_blendtable[p1[w]&0xff][a3]+g_blendtable[p1[w+1]&0xff][a4];
t|=(g_blendtable[(p1[0]>>8)&0xff][a1]+g_blendtable[(p1[1]>>8)&0xff][a2]+g_blendtable[(p1[w]>>8)&0xff][a3]+g_blendtable[(p1[w+1]>>8)&0xff][a4])<<8;
t|=(g_blendtable[(p1[0]>>16)&0xff][a1]+g_blendtable[(p1[1]>>16)&0xff][a2]+g_blendtable[(p1[w]>>16)&0xff][a3]+g_blendtable[(p1[w+1]>>16)&0xff][a4])<<16;
return t;
#else
__asm
{
movd mm6, xp
mov eax, p1
movd mm7, yp
mov esi, w
movq mm4, mmx_blend4_revn
punpcklwd mm6,mm6
movq mm5, mmx_blend4_revn
punpcklwd mm7,mm7
movd mm0, [eax]
punpckldq mm6,mm6
movd mm1, [eax+4]
punpckldq mm7,mm7
movd mm2, [eax+esi*4]
punpcklbw mm0, [mmx_blend4_zero]
movd mm3, [eax+esi*4+4]
psubw mm4, mm6
punpcklbw mm1, [mmx_blend4_zero]
pmullw mm0, mm4
punpcklbw mm2, [mmx_blend4_zero]
pmullw mm1, mm6
punpcklbw mm3, [mmx_blend4_zero]
psubw mm5, mm7
pmullw mm2, mm4
pmullw mm3, mm6
paddw mm0, mm1
// stall (mm0)
psrlw mm0, 8
// stall (waiting for mm3/mm2)
paddw mm2, mm3
pmullw mm0, mm5
psrlw mm2, 8
// stall (mm2)
pmullw mm2, mm7
// stall
// stall (mm2)
paddw mm0, mm2
// stall
psrlw mm0, 8
// stall
packuswb mm0, mm0
// stall
movd eax, mm0
}
#endif
}
static __inline unsigned int BLEND4_16(unsigned int *p1, unsigned int w, int xp, int yp)
{
#ifdef NO_MMX
register int t;
unsigned char a1,a2,a3,a4;
xp=(xp>>8)&0xff;
yp=(yp>>8)&0xff;
a1=g_blendtable[255-xp][255-yp];
a2=g_blendtable[xp][255-yp];
a3=g_blendtable[255-xp][yp];
a4=g_blendtable[xp][yp];
t=g_blendtable[p1[0]&0xff][a1]+g_blendtable[p1[1]&0xff][a2]+g_blendtable[p1[w]&0xff][a3]+g_blendtable[p1[w+1]&0xff][a4];
t|=(g_blendtable[(p1[0]>>8)&0xff][a1]+g_blendtable[(p1[1]>>8)&0xff][a2]+g_blendtable[(p1[w]>>8)&0xff][a3]+g_blendtable[(p1[w+1]>>8)&0xff][a4])<<8;
t|=(g_blendtable[(p1[0]>>16)&0xff][a1]+g_blendtable[(p1[1]>>16)&0xff][a2]+g_blendtable[(p1[w]>>16)&0xff][a3]+g_blendtable[(p1[w+1]>>16)&0xff][a4])<<16;
return t;
#else
__asm
{
movd mm6, xp
mov eax, p1
movd mm7, yp
mov esi, w
movq mm4, mmx_blend4_revn
psrlw mm6, 8
movq mm5, mmx_blend4_revn
psrlw mm7, 8
movd mm0, [eax]
punpcklwd mm6,mm6
movd mm1, [eax+4]
punpcklwd mm7,mm7
movd mm2, [eax+esi*4]
punpckldq mm6,mm6
movd mm3, [eax+esi*4+4]
punpckldq mm7,mm7
punpcklbw mm0, [mmx_blend4_zero]
psubw mm4, mm6
punpcklbw mm1, [mmx_blend4_zero]
pmullw mm0, mm4
punpcklbw mm2, [mmx_blend4_zero]
pmullw mm1, mm6
punpcklbw mm3, [mmx_blend4_zero]
psubw mm5, mm7
pmullw mm2, mm4
pmullw mm3, mm6
paddw mm0, mm1
// stall (mm0)
psrlw mm0, 8
// stall (waiting for mm3/mm2)
paddw mm2, mm3
pmullw mm0, mm5
psrlw mm2, 8
// stall (mm2)
pmullw mm2, mm7
// stall
// stall (mm2)
paddw mm0, mm2
// stall
psrlw mm0, 8
// stall
packuswb mm0, mm0
// stall
movd eax, mm0
}
#endif
}
#pragma warning( pop )
static __inline void mmx_avgblend_block(int *output, int *input, int l)
{
#ifdef NO_MMX
while (l--)
{
*output=BLEND_AVG(*input++,*output);
output++;
}
#else
static int mask[2]=
{
~((1<<7)|(1<<15)|(1<<23)),
~((1<<7)|(1<<15)|(1<<23))
};
__asm
{
mov eax, input
mov edi, output
mov ecx, l
shr ecx, 2
align 16
mmx_avgblend_loop:
movq mm0, [eax]
movq mm1, [edi]
psrlq mm0, 1
movq mm2, [eax+8]
psrlq mm1, 1
movq mm3, [edi+8]
psrlq mm2, 1
pand mm0, [mask]
psrlq mm3, 1
pand mm1, [mask]
pand mm2, [mask]
paddusb mm0, mm1
pand mm3, [mask]
add eax, 16
paddusb mm2, mm3
movq [edi], mm0
movq [edi+8], mm2
add edi, 16
dec ecx
jnz mmx_avgblend_loop
emms
};
#endif
}
static __inline void mmx_addblend_block(int *output, int *input, int l)
{
#ifdef NO_MMX
while (l--)
{
*output=BLEND(*input++,*output);
output++;
}
#else
__asm
{
mov eax, input
mov edi, output
mov ecx, l
shr ecx, 2
align 16
mmx_addblend_loop:
movq mm0, [eax]
movq mm1, [edi]
movq mm2, [eax+8]
movq mm3, [edi+8]
paddusb mm0, mm1
paddusb mm2, mm3
add eax, 16
movq [edi], mm0
movq [edi+8], mm2
add edi, 16
dec ecx
jnz mmx_addblend_loop
emms
};
#endif
}
static __inline void mmx_mulblend_block(int *output, int *input, int l)
{
#ifdef NO_MMX
while (l--)
{
*output=BLEND_MUL(*input++,*output);
output++;
}
#else
__asm
{
mov eax, input
mov edi, output
mov ecx, l
shr ecx, 1
align 16
mmx_mulblend_loop:
movd mm0, [eax]
movd mm1, [edi]
movd mm2, [eax+4]
punpcklbw mm0, [mmx_blend4_zero]
movd mm3, [edi+4]
punpcklbw mm1, [mmx_blend4_zero]
punpcklbw mm2, [mmx_blend4_zero]
pmullw mm0, mm1
punpcklbw mm3, [mmx_blend4_zero]
psrlw mm0, 8
pmullw mm2, mm3
packuswb mm0, mm0
psrlw mm2, 8
packuswb mm2, mm2
add eax, 8
movd [edi], mm0
movd [edi+4], mm2
add edi, 8
dec ecx
jnz mmx_mulblend_loop
emms
};
#endif
}
static void __inline mmx_adjblend_block(int *o, int *in1, int *in2, int len, int v)
{
#ifdef NO_MMX
while (len--)
{
*o++=BLEND_ADJ(*in1++,*in2++,inblendval);
}
#else
__asm
{
movd mm3, [v] // VVVVVVVV
mov ecx, len
packuswb mm3, mm3 // 0000HHVV
mov edx, o
punpcklwd mm3, mm3 // HHVVHHVV
mov esi, in1
movq mm4, [mmx_blend4_revn]
punpckldq mm3, mm3 // HHVVHHVV HHVVHHVV
pand mm3, [mmx_blendadj_mask]
mov edi, in2
shr ecx, 1
psubw mm4, mm3
align 16
_mmx_adjblend_loop:
movd mm0, [esi]
movd mm1, [edi]
punpcklbw mm0, [mmx_blend4_zero]
movd mm6, [esi+4]
punpcklbw mm1, [mmx_blend4_zero]
movd mm7, [edi+4]
punpcklbw mm6, [mmx_blend4_zero]
pmullw mm0, mm3
punpcklbw mm7, [mmx_blend4_zero]
pmullw mm1, mm4
pmullw mm6, mm3
pmullw mm7, mm4
paddw mm0, mm1
paddw mm6, mm7
add edi, 8
psrlw mm0, 8
add esi, 8
psrlw mm6, 8
packuswb mm0, mm0
packuswb mm6, mm6
movd [edx], mm0
movd [edx+4], mm6
add edx, 8
dec ecx
jnz _mmx_adjblend_loop
emms
};
#endif
}
class RString
{
public:
RString() { m_str=0; m_size=0; }
~RString() { if (m_str) GlobalFree(m_str); };
void resize(int size) { m_size=size; if (m_str) GlobalFree(m_str); m_str=0; if (size) m_str=(char*)GlobalAlloc(GPTR,size); }
char *get() { return m_str; }
int getsize() { if (!m_str) return 0; return m_size; }
void assign(char *s) { resize(strlen(s)+1); strcpy(m_str,s); }
void get_from_dlgitem(HWND hwnd, int dlgItem)
{
int l=SendDlgItemMessage(hwnd,dlgItem,WM_GETTEXTLENGTH,0,0);
if ( l < 256) l=256;
resize(l+1+256);
GetDlgItemText(hwnd,dlgItem, m_str, l+1);
m_str[l]=0;
}
private:
char *m_str;
int m_size;
};
void doAVSEvalHighLight(HWND hwndDlg, UINT sub, char *data);
#include "laser/laserline.h"
#endif