453 lines
12 KiB
C++
453 lines
12 KiB
C++
//**************************************************************
|
|
//* OpenGLide - Glide to OpenGL Wrapper
|
|
//* http://openglide.sourceforge.net
|
|
//*
|
|
//* OpenGL Extensions
|
|
//*
|
|
//* OpenGLide is OpenSource under LGPL license
|
|
//* Originaly made by Fabio Barros
|
|
//* Modified by Paul for Glidos (http://www.glidos.net)
|
|
//* Mac version and additional features by Jens-Olaf Hemprich
|
|
//**************************************************************
|
|
|
|
#include "FormatConversion.h"
|
|
|
|
|
|
void Convert565to8888( FxU16 *Buffer1, FxU32 *Buffer2, FxU32 Pixels )
|
|
{
|
|
while ( Pixels )
|
|
{
|
|
*Buffer2++ = 0xFF000000 | // A
|
|
( (*Buffer1) & 0x001F ) << 19 | // B
|
|
( (*Buffer1) & 0x07E0 ) << 5 | // G
|
|
( (*Buffer1++) & 0xF800 ) >> 8; // R
|
|
Pixels--;
|
|
}
|
|
}
|
|
|
|
void Convert565Kto8888( FxU16 *Buffer1, FxU16 key, FxU32 *Buffer2, FxU32 Pixels )
|
|
{
|
|
while ( Pixels )
|
|
{
|
|
*Buffer2++ = ( ( (*Buffer1) == key) ? 0x00000000 : 0xFF000000 ) | // A
|
|
( (*Buffer1) & 0x001F ) << 19 | // B
|
|
( (*Buffer1) & 0x07E0 ) << 5 | // G
|
|
( (*Buffer1++) & 0xF800 ) >> 8; // R
|
|
Pixels--;
|
|
}
|
|
}
|
|
|
|
// This functions processes 2 pixels at a time, there is no problem in
|
|
// passing odd numbers or a number less than 2 for the pixels, but
|
|
// the buffers should be large enough
|
|
void Convert565to5551( FxU32 *Buffer1, FxU32 *Buffer2, int Pixels )
|
|
{
|
|
while ( Pixels > 0 )
|
|
{
|
|
*Buffer2++ = ( (*Buffer1) & 0xFFC0FFC0 ) |
|
|
( ( (*Buffer1++) & 0x001F001F ) << 1 ) |
|
|
0x00010001;
|
|
Pixels -= 2;
|
|
}
|
|
}
|
|
|
|
// This functions processes 2 pixels at a time, there is no problem in
|
|
// passing odd numbers or a number less than 2 for the pixels, but
|
|
// the buffers should be large enough
|
|
void Convert5551to565( FxU32 *Buffer1, FxU32 *Buffer2, int Pixels )
|
|
{
|
|
while ( Pixels > 0 )
|
|
{
|
|
*Buffer2++ = ( (*Buffer1) & 0xFFC0FFC0 ) |
|
|
( ( (*Buffer1++) & 0x003E003E ) >> 1 );
|
|
Pixels -= 2;
|
|
}
|
|
}
|
|
|
|
// This functions processes 2 pixels at a time, there is no problem in
|
|
// passing odd numbers or a number less than 2 for the pixels, but
|
|
// the buffers should be large enough
|
|
void Convert4444to4444special( FxU32 *Buffer1, FxU32 *Buffer2, int Pixels )
|
|
{
|
|
while ( Pixels > 0 )
|
|
{
|
|
*Buffer2++ = ( ( (*Buffer1) & 0x0FFF0FFF ) << 4 )|
|
|
( ( (*Buffer1++) & 0xF000F000 ) >> 12 );
|
|
Pixels -= 2;
|
|
}
|
|
}
|
|
|
|
void Convert1555to5551( FxU32 *Buffer1, FxU32 *Buffer2, int Pixels )
|
|
{
|
|
while ( Pixels > 0 )
|
|
{
|
|
*Buffer2++ = ( ( (*Buffer1) & 0x7FFF7FFF ) << 1 )|
|
|
( ( (*Buffer1++) & 0x80008000 ) >> 15 );
|
|
Pixels -= 2;
|
|
}
|
|
}
|
|
|
|
unsigned __int64 Mask565_5551_1 = 0xFFC0FFC0FFC0FFC0;
|
|
unsigned __int64 Mask565_5551_2 = 0x001F001F001F001F;
|
|
unsigned __int64 Mask565_5551_3 = 0x0001000100010001;
|
|
|
|
// This functions processes 4 pixels at a time, there is no problem in
|
|
// passing odd numbers or a number less than 4 for the pixels, but
|
|
// the buffers should be large enough
|
|
void MMXConvert565to5551( void *Src, void *Dst, int NumberOfPixels )
|
|
{
|
|
__asm
|
|
{
|
|
mov ecx, NumberOfPixels
|
|
mov eax, Src
|
|
shl ecx, 1
|
|
mov edx, Dst
|
|
movq mm6, [Mask565_5551_3]
|
|
movq mm5, [Mask565_5551_2]
|
|
movq mm4, [Mask565_5551_1]
|
|
align 16
|
|
copying:
|
|
movq mm0, [eax + ecx]
|
|
movq mm1, mm6
|
|
movq mm2, mm0
|
|
|
|
pand mm0, mm5
|
|
pand mm2, mm4
|
|
psllq mm0, 1
|
|
por mm1, mm2
|
|
por mm0, mm1
|
|
|
|
movq [edx + ecx], mm0
|
|
sub ecx, 8
|
|
jg copying
|
|
EMMS
|
|
}
|
|
}
|
|
|
|
// This functions processes 4 pixels at a time, there is no problem in
|
|
// passing odd numbers or a number less than 4 for the pixels, but
|
|
// the buffers should be large enough
|
|
void MMXConvert565Kto5551( void *Src, FxU32 key, void *Dst, int NumberOfPixels )
|
|
{
|
|
__asm
|
|
{
|
|
mov ecx, NumberOfPixels
|
|
mov eax, Src
|
|
shl ecx, 1
|
|
mov edx, Dst
|
|
movq mm6, [Mask565_5551_3]
|
|
movq mm5, [Mask565_5551_2]
|
|
movq mm4, [Mask565_5551_1]
|
|
movd mm7, key
|
|
movq mm0, mm7
|
|
psllq mm0, 16
|
|
por mm7, mm0
|
|
movq mm0, mm7
|
|
psllq mm0, 32
|
|
por mm7, mm0
|
|
align 16
|
|
copying:
|
|
movq mm3, mm7
|
|
movq mm0, [eax + ecx]
|
|
movq mm1, mm6
|
|
movq mm2, mm0
|
|
|
|
// Comparing
|
|
pcmpeqw mm3, mm0
|
|
|
|
pand mm0, mm5
|
|
pand mm2, mm4
|
|
psllq mm0, 1
|
|
por mm1, mm2
|
|
por mm0, mm1
|
|
|
|
// Applying key
|
|
pandn mm3, mm0
|
|
|
|
movq [edx + ecx], mm3
|
|
sub ecx, 8
|
|
jg copying
|
|
EMMS
|
|
}
|
|
}
|
|
|
|
unsigned __int64 Mask5551_565_1 = 0xFFC0FFC0FFC0FFC0;
|
|
unsigned __int64 Mask5551_565_2 = 0x003E003E003E003E;
|
|
|
|
// This functions processes 4 pixels at a time, there is no problem in
|
|
// passing odd numbers or a number less than 4 for the pixels, but
|
|
// the buffers should be large enough
|
|
void MMXConvert5551to565( void *Src, void *Dst, int NumberOfPixels )
|
|
{
|
|
__asm
|
|
{
|
|
mov ecx, NumberOfPixels
|
|
mov eax, Src
|
|
shl ecx, 1
|
|
mov edx, Dst
|
|
movq mm5, [Mask5551_565_2]
|
|
movq mm4, [Mask5551_565_1]
|
|
align 16
|
|
copying:
|
|
movq mm0, [eax + ecx]
|
|
movq mm2, mm0
|
|
|
|
pand mm0, mm5
|
|
pand mm2, mm4
|
|
psrlq mm0, 1
|
|
por mm0, mm2
|
|
|
|
movq [edx + ecx], mm0
|
|
sub ecx, 8
|
|
jg copying
|
|
EMMS
|
|
}
|
|
}
|
|
|
|
unsigned __int64 Mask4444_1 = 0x0FFF0FFF0FFF0FFF;
|
|
unsigned __int64 Mask4444_2 = 0xF000F000F000F000;
|
|
|
|
// This functions processes 4 pixels at a time, there is no problem in
|
|
// passing odd numbers or a number less than 4 for the pixels, but
|
|
// the buffers should be large enough
|
|
void MMXConvert4444to4444special( void *Src, void *Dst, int NumberOfPixels )
|
|
{
|
|
__asm
|
|
{
|
|
mov ecx, NumberOfPixels
|
|
mov eax, Src
|
|
shl ecx, 1
|
|
mov edx, Dst
|
|
movq mm7, [Mask4444_2]
|
|
movq mm6, [Mask4444_1]
|
|
align 16
|
|
copying:
|
|
movq mm0, [eax + ecx]
|
|
movq mm1, mm0
|
|
|
|
pand mm0, mm6
|
|
pand mm1, mm7
|
|
psllq mm0, 4
|
|
psrlq mm1, 12
|
|
por mm0, mm1
|
|
|
|
movq [edx + ecx], mm0
|
|
sub ecx, 8
|
|
jg copying
|
|
EMMS
|
|
}
|
|
}
|
|
|
|
unsigned __int64 Mask5551_1 = 0x7FFF7FFF7FFF7FFF;
|
|
unsigned __int64 Mask5551_2 = 0x8000800080008000;
|
|
|
|
// This functions processes 4 pixels at a time, there is no problem in
|
|
// passing odd numbers or a number less than 4 for the pixels, but
|
|
// the buffers should be large enough
|
|
void MMXConvert1555to5551( void *Src, void *Dst, int NumberOfPixels )
|
|
{
|
|
__asm
|
|
{
|
|
mov ecx, NumberOfPixels
|
|
mov eax, Src
|
|
shl ecx, 1
|
|
mov edx, Dst
|
|
movq mm7, [Mask4444_2]
|
|
movq mm6, [Mask4444_1]
|
|
align 16
|
|
copying:
|
|
movq mm0, [eax + ecx]
|
|
movq mm1, mm0
|
|
|
|
pand mm0, mm6
|
|
pand mm1, mm7
|
|
psllq mm0, 1
|
|
psrlq mm1, 15
|
|
por mm0, mm1
|
|
|
|
movq [edx + ecx], mm0
|
|
sub ecx, 8
|
|
jg copying
|
|
EMMS
|
|
}
|
|
}
|
|
|
|
FxU8 Mask565A[8] = { 0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF };
|
|
FxU8 Mask565B[8] = { 0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8 };
|
|
FxU8 Mask565G[8] = { 0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07 };
|
|
FxU8 Mask565R[8] = { 0x1F,0x00,0x1F,0x00,0x1F,0x00,0x1F,0x00 };
|
|
|
|
void MMXConvert565to8888( void *Src, void *Dst, FxU32 NumberOfPixels )
|
|
{
|
|
// FxU16 entered is ARGB
|
|
// Has to be ABGR
|
|
__asm
|
|
{
|
|
MOVQ MM7, [Mask565A]
|
|
mov ECX, NumberOfPixels
|
|
MOVQ MM6, [Mask565B]
|
|
mov EAX, Src
|
|
MOVQ MM5, [Mask565G]
|
|
MOVQ MM4, [Mask565R]
|
|
mov EDX, Dst
|
|
copying:
|
|
MOVQ MM0, [EAX]
|
|
add EAX, 8
|
|
MOVQ MM2, MM0
|
|
MOVQ MM1, MM0
|
|
|
|
PAND MM0, MM4 // Mask R
|
|
PAND MM2, MM6 // Mask B
|
|
PSLLW MM0, 11 // Shift R
|
|
PAND MM1, MM5 // Mask G
|
|
|
|
PSRLW MM2, 8 // Shift B
|
|
|
|
MOVQ MM3, MM1
|
|
PSLLW MM1, 13
|
|
POR MM0, MM2
|
|
PSRLW MM3, 3
|
|
POR MM1, MM3
|
|
|
|
POR MM1, MM7
|
|
|
|
MOVQ MM2, MM0
|
|
PUNPCKHBW MM0, MM1
|
|
PUNPCKLBW MM2, MM1
|
|
|
|
// Storing Unpacked
|
|
MOVQ [EDX], MM2
|
|
add EDX, 16
|
|
MOVQ [EDX-8], MM0
|
|
sub ECX, 4
|
|
jg copying
|
|
EMMS
|
|
}
|
|
}
|
|
|
|
void ConvertA8toAP88( FxU8 *Buffer1, FxU16 *Buffer2, FxU32 Pixels )
|
|
{
|
|
while ( Pixels )
|
|
{
|
|
*Buffer2 = ( ( ( *Buffer1 ) << 8 ) | ( *Buffer1 ) );
|
|
Buffer1++;
|
|
Buffer2++;
|
|
Pixels--;
|
|
}
|
|
}
|
|
|
|
void Convert8332to8888( FxU16 *Buffer1, FxU32 *Buffer2, FxU32 Pixels )
|
|
{
|
|
static FxU32 R,
|
|
G,
|
|
B,
|
|
A;
|
|
for ( FxU32 i = Pixels; i > 0; i-- )
|
|
{
|
|
A = ( ( ( *Buffer1 ) >> 8 ) & 0xFF );
|
|
R = ( ( ( *Buffer1 ) >> 5 ) & 0x07 ) << 5;
|
|
G = ( ( ( *Buffer1 ) >> 2 ) & 0x07 ) << 5;
|
|
B = ( ( *Buffer1 ) & 0x03 ) << 6;
|
|
*Buffer2 = ( A << 24 ) | ( B << 16 ) | ( G << 8 ) | R;
|
|
Buffer1++;
|
|
Buffer2++;
|
|
}
|
|
}
|
|
|
|
void ConvertP8to8888( FxU8 *Buffer1, FxU32 *Buffer2, FxU32 Pixels, FxU32 *palette )
|
|
{
|
|
while ( Pixels-- )
|
|
{
|
|
*Buffer2++ = palette[ *Buffer1++ ];
|
|
}
|
|
}
|
|
|
|
void ConvertAI44toAP88( FxU8 *Buffer1, FxU16 *Buffer2, FxU32 Pixels )
|
|
{
|
|
for ( FxU32 i = Pixels; i > 0; i-- )
|
|
{
|
|
*Buffer2 = ( ( ( ( *Buffer1 ) & 0xF0 ) << 8 ) | ( ( ( *Buffer1 ) & 0x0F ) << 4 ) );
|
|
Buffer2++;
|
|
Buffer1++;
|
|
}
|
|
}
|
|
|
|
void ConvertAP88to8888( FxU16 *Buffer1, FxU32 *Buffer2, FxU32 Pixels, FxU32 *palette )
|
|
{
|
|
FxU32 RGB,
|
|
A;
|
|
for ( FxU32 i = Pixels; i > 0; i-- )
|
|
{
|
|
RGB = ( palette[ *Buffer1 & 0x00FF ] & 0x00FFFFFF );
|
|
A = *Buffer1 >> 8;
|
|
*Buffer2 = ( A << 24 ) | RGB;
|
|
Buffer1++;
|
|
Buffer2++;
|
|
}
|
|
}
|
|
|
|
void ConvertYIQto8888( FxU8 *in, FxU32 *out, FxU32 Pixels, GuNccTable *ncc )
|
|
{
|
|
LONG R;
|
|
LONG G;
|
|
LONG B;
|
|
|
|
for ( FxU32 i = Pixels; i > 0; i-- )
|
|
{
|
|
R = ncc->yRGB[ *in >> 4 ] + ncc->iRGB[ ( *in >> 2 ) & 0x3 ][ 0 ]
|
|
+ ncc->qRGB[ ( *in ) & 0x3 ][ 0 ];
|
|
|
|
G = ncc->yRGB[ *in >> 4 ] + ncc->iRGB[ ( *in >> 2 ) & 0x3 ][ 1 ]
|
|
+ ncc->qRGB[ ( *in ) & 0x3 ][ 1 ];
|
|
|
|
B = ncc->yRGB[ *in >> 4 ] + ncc->iRGB[ ( *in >> 2 ) & 0x3 ][ 2 ]
|
|
+ ncc->qRGB[ ( *in ) & 0x3 ][ 2 ];
|
|
|
|
R = ( ( R < 0 ) ? 0 : ( ( R > 255 ) ? 255 : R ) );
|
|
G = ( ( G < 0 ) ? 0 : ( ( G > 255 ) ? 255 : G ) );
|
|
B = ( ( B < 0 ) ? 0 : ( ( B > 255 ) ? 255 : B ) );
|
|
|
|
*out = ( R | ( G << 8 ) | ( B << 16 ) | 0xff000000 );
|
|
|
|
in++;
|
|
out++;
|
|
}
|
|
}
|
|
|
|
void ConvertAYIQto8888( FxU16 *in, FxU32 *out, FxU32 Pixels, GuNccTable *ncc)
|
|
{
|
|
LONG R;
|
|
LONG G;
|
|
LONG B;
|
|
|
|
for ( FxU32 i = Pixels; i > 0; i-- )
|
|
{
|
|
R = ncc->yRGB[ ( *in >> 4 ) & 0xf ] + ncc->iRGB[ ( *in >> 2 ) & 0x3 ][ 0 ]
|
|
+ ncc->qRGB[ ( *in ) & 0x3 ][ 0 ];
|
|
|
|
G = ncc->yRGB[ ( *in >> 4 ) & 0xf ] + ncc->iRGB[ ( *in >> 2 ) & 0x3 ][ 1 ]
|
|
+ ncc->qRGB[ ( *in ) & 0x3 ][ 1 ];
|
|
|
|
B = ncc->yRGB[ ( *in >> 4 ) & 0xf ] + ncc->iRGB[ ( *in >> 2 ) & 0x3 ][ 2 ]
|
|
+ ncc->qRGB[ ( *in ) & 0x3 ][ 2 ];
|
|
|
|
R = ( ( R < 0 ) ? 0 : ( ( R > 255 ) ? 255 : R ) );
|
|
G = ( ( G < 0 ) ? 0 : ( ( G > 255 ) ? 255 : G ) );
|
|
B = ( ( B < 0 ) ? 0 : ( ( B > 255 ) ? 255 : B ) );
|
|
|
|
*out = ( R | ( G << 8 ) | ( B << 16 ) | ( 0xff000000 & ( *in << 16 ) ) );
|
|
|
|
in++;
|
|
out++;
|
|
}
|
|
}
|
|
|
|
void SplitAP88( FxU16 *ap88, FxU8 *index, FxU8 *alpha, FxU32 pixels )
|
|
{
|
|
for ( FxU32 i = pixels; i > 0; i-- )
|
|
{
|
|
*alpha++ = ( *ap88 >> 8 );
|
|
*index++ = ( *ap88++ & 0xff );
|
|
}
|
|
}
|