GlideHQ: Add
This commit is contained in:
parent
9e9fdc25bc
commit
e928a5995d
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Texture Filtering
|
||||
* Version: 1.0
|
||||
*
|
||||
* Copyright (C) 2007 Hiroshi Morii All Rights Reserved.
|
||||
* Email koolsmoky(at)users.sourceforge.net
|
||||
* Web http://www.3dfxzone.it/koolsmoky
|
||||
*
|
||||
* this 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* this 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <memory.h>
|
||||
#include <stdlib.h>
|
||||
#include "Ext_TxFilter.h"
|
||||
|
|
@ -0,0 +1,212 @@
|
|||
/*
|
||||
* Texture Filtering
|
||||
* Version: 1.0
|
||||
*
|
||||
* Copyright (C) 2007 Hiroshi Morii All Rights Reserved.
|
||||
* Email koolsmoky(at)users.sourceforge.net
|
||||
* Web http://www.3dfxzone.it/koolsmoky
|
||||
*
|
||||
* this 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* this 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __EXT_TXFILTER_H__
|
||||
#define __EXT_TXFILTER_H__
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#define TXHMODULE HMODULE
|
||||
#define DLOPEN(a) LoadLibraryW(a)
|
||||
#define DLCLOSE(a) FreeLibrary(a)
|
||||
#define DLSYM(a, b) GetProcAddress(a, b)
|
||||
#define GETCWD(a, b) GetCurrentDirectoryW(a, b)
|
||||
#define CHDIR(a) SetCurrentDirectoryW(a)
|
||||
#else
|
||||
#include <iostream>
|
||||
#include <dlfcn.h>
|
||||
#define MAX_PATH 4095
|
||||
#define TXHMODULE void*
|
||||
#define DLOPEN(a) dlopen(a, RTLD_LAZY|RTLD_GLOBAL)
|
||||
#define DLCLOSE(a) dlclose(a)
|
||||
#define DLSYM(a, b) dlsym(a, b)
|
||||
#define GETCWD(a, b) getcwd(b, a)
|
||||
#define CHDIR(a) chdir(a)
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
typedef __int64 int64;
|
||||
typedef unsigned __int64 uint64;
|
||||
typedef unsigned char boolean;
|
||||
#else
|
||||
typedef long long int64;
|
||||
typedef unsigned long long uint64;
|
||||
typedef unsigned char boolean;
|
||||
#endif
|
||||
|
||||
#define NO_OPTIONS 0x00000000
|
||||
|
||||
#define FILTER_MASK 0x000000ff
|
||||
#define NO_FILTER 0x00000000
|
||||
#define SMOOTH_FILTER_MASK 0x0000000f
|
||||
#define NO_SMOOTH_FILTER 0x00000000
|
||||
#define SMOOTH_FILTER_1 0x00000001
|
||||
#define SMOOTH_FILTER_2 0x00000002
|
||||
#define SMOOTH_FILTER_3 0x00000003
|
||||
#define SMOOTH_FILTER_4 0x00000004
|
||||
#define SHARP_FILTER_MASK 0x000000f0
|
||||
#define NO_SHARP_FILTER 0x00000000
|
||||
#define SHARP_FILTER_1 0x00000010
|
||||
#define SHARP_FILTER_2 0x00000020
|
||||
|
||||
#define ENHANCEMENT_MASK 0x00000f00
|
||||
#define NO_ENHANCEMENT 0x00000000
|
||||
#define X2_ENHANCEMENT 0x00000100
|
||||
#define X2SAI_ENHANCEMENT 0x00000200
|
||||
#define HQ2X_ENHANCEMENT 0x00000300
|
||||
#define LQ2X_ENHANCEMENT 0x00000400
|
||||
#define HQ4X_ENHANCEMENT 0x00000500
|
||||
#define HQ2XS_ENHANCEMENT 0x00000600
|
||||
#define LQ2XS_ENHANCEMENT 0x00000700
|
||||
|
||||
#define COMPRESSION_MASK 0x0000f000
|
||||
#define NO_COMPRESSION 0x00000000
|
||||
#define FXT1_COMPRESSION 0x00001000
|
||||
#define NCC_COMPRESSION 0x00002000
|
||||
#define S3TC_COMPRESSION 0x00003000
|
||||
|
||||
#define HIRESTEXTURES_MASK 0x000f0000
|
||||
#define NO_HIRESTEXTURES 0x00000000
|
||||
#define GHQ_HIRESTEXTURES 0x00010000
|
||||
#define RICE_HIRESTEXTURES 0x00020000
|
||||
#define JABO_HIRESTEXTURES 0x00030000
|
||||
|
||||
#define COMPRESS_TEX 0x00100000
|
||||
#define COMPRESS_HIRESTEX 0x00200000
|
||||
#define GZ_TEXCACHE 0x00400000
|
||||
#define GZ_HIRESTEXCACHE 0x00800000
|
||||
#define DUMP_TEXCACHE 0x01000000
|
||||
#define DUMP_HIRESTEXCACHE 0x02000000
|
||||
#define TILE_HIRESTEX 0x04000000
|
||||
#define UNDEFINED_0 0x08000000
|
||||
#define FORCE16BPP_HIRESTEX 0x10000000
|
||||
#define FORCE16BPP_TEX 0x20000000
|
||||
#define LET_TEXARTISTS_FLY 0x40000000 /* a little freedom for texture artists */
|
||||
#define DUMP_TEX 0x80000000
|
||||
|
||||
#ifndef __GLIDE_H__ /* GLIDE3 */
|
||||
/* from 3Dfx Interactive Inc. glide.h */
|
||||
#define GR_TEXFMT_ALPHA_8 0x2
|
||||
#define GR_TEXFMT_INTENSITY_8 0x3
|
||||
|
||||
#define GR_TEXFMT_ALPHA_INTENSITY_44 0x4
|
||||
#define GR_TEXFMT_P_8 0x5
|
||||
|
||||
#define GR_TEXFMT_RGB_565 0xa
|
||||
#define GR_TEXFMT_ARGB_1555 0xb
|
||||
#define GR_TEXFMT_ARGB_4444 0xc
|
||||
#define GR_TEXFMT_ALPHA_INTENSITY_88 0xd
|
||||
|
||||
/* from 3Dfx Interactive Inc. g3ext.h */
|
||||
#define GR_TEXFMT_ARGB_CMP_FXT1 0x11
|
||||
|
||||
#define GR_TEXFMT_ARGB_8888 0x12
|
||||
|
||||
#define GR_TEXFMT_ARGB_CMP_DXT1 0x16
|
||||
#define GR_TEXFMT_ARGB_CMP_DXT3 0x18
|
||||
#define GR_TEXFMT_ARGB_CMP_DXT5 0x1A
|
||||
#endif /* GLIDE3 */
|
||||
|
||||
struct GHQTexInfo {
|
||||
unsigned char *data;
|
||||
int width;
|
||||
int height;
|
||||
unsigned short format;
|
||||
|
||||
int smallLodLog2;
|
||||
int largeLodLog2;
|
||||
int aspectRatioLog2;
|
||||
|
||||
int tiles;
|
||||
int untiled_width;
|
||||
int untiled_height;
|
||||
|
||||
unsigned char is_hires_tex;
|
||||
};
|
||||
|
||||
/* Callback to display hires texture info.
|
||||
* Gonetz <gonetz(at)ngs.ru>
|
||||
*
|
||||
* void DispInfo(const char *format, ...)
|
||||
* {
|
||||
* va_list args;
|
||||
* char buf[INFO_BUF];
|
||||
*
|
||||
* va_start(args, format);
|
||||
* vsprintf(buf, format, args);
|
||||
* va_end(args);
|
||||
*
|
||||
* printf(buf);
|
||||
* }
|
||||
*/
|
||||
#define INFO_BUF 4095
|
||||
typedef void (*dispInfoFuncExt)(const wchar_t *format, ...);
|
||||
|
||||
#ifndef TXFILTER_DLL
|
||||
boolean ext_ghq_init(int maxwidth, /* maximum texture width supported by hardware */
|
||||
int maxheight,/* maximum texture height supported by hardware */
|
||||
int maxbpp, /* maximum texture bpp supported by hardware */
|
||||
int options, /* options */
|
||||
int cachesize,/* cache textures to system memory */
|
||||
wchar_t *path, /* plugin directory. must be smaller than MAX_PATH */
|
||||
wchar_t *ident, /* name of ROM. must be no longer than 64 in character. */
|
||||
dispInfoFuncExt callback /* callback function to display info */
|
||||
);
|
||||
|
||||
void ext_ghq_shutdown(void);
|
||||
|
||||
boolean ext_ghq_txfilter(unsigned char *src, /* input texture */
|
||||
int srcwidth, /* width of input texture */
|
||||
int srcheight, /* height of input texture */
|
||||
unsigned short srcformat, /* format of input texture */
|
||||
uint64 g64crc, /* glide64 crc */
|
||||
GHQTexInfo *info /* output */
|
||||
);
|
||||
|
||||
boolean ext_ghq_hirestex(uint64 g64crc, /* glide64 crc */
|
||||
uint64 r_crc64, /* checksum hi:palette low:texture */
|
||||
unsigned short *palette, /* palette for CI textures */
|
||||
GHQTexInfo *info /* output */
|
||||
);
|
||||
|
||||
uint64 ext_ghq_checksum(unsigned char *src, /* input texture */
|
||||
int width, /* width of texture */
|
||||
int height, /* height of texture */
|
||||
int size, /* type of texture pixel */
|
||||
int rowStride, /* row stride in bytes */
|
||||
unsigned char *palette /* palette */
|
||||
);
|
||||
|
||||
boolean ext_ghq_dmptx(unsigned char *src, /* input texture (must be in 3Dfx Glide format) */
|
||||
int width, /* width of texture */
|
||||
int height, /* height of texture */
|
||||
int rowStridePixel, /* row stride of input texture in pixels */
|
||||
unsigned short gfmt, /* glide format of input texture */
|
||||
unsigned short n64fmt,/* N64 format hi:format low:size */
|
||||
uint64 r_crc64 /* checksum hi:palette low:texture */
|
||||
);
|
||||
|
||||
boolean ext_ghq_reloadhirestex();
|
||||
#endif /* TXFILTER_DLL */
|
||||
|
||||
#endif /* __EXT_TXFILTER_H__ */
|
|
@ -0,0 +1,295 @@
|
|||
<?xml version="1.0" encoding="shift_jis"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="GlideHQ"
|
||||
ProjectGUID="{2DADDAA5-0F57-46ED-A974-747908DDC7F3}"
|
||||
RootNamespace="GlideHQ"
|
||||
TargetFrameworkVersion="0"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
ConfigurationType="4"
|
||||
InheritedPropertySheets="$(SolutionDir)PropertySheets/Win32.Debug.vsprops"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""$(Root)Source/3rd Party/wx/src";inc"
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
ConfigurationType="4"
|
||||
InheritedPropertySheets="$(SolutionDir)PropertySheets/Win32.Release.vsprops"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="inc"
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath="Ext_TxFilter.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="TextureFilters.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="TextureFilters_2xsai.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="TextureFilters_hq2x.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="TextureFilters_hq4x.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="TxCache.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="TxDbg.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="TxFilter.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="TxFilterExport.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="TxHiResCache.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="TxImage.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="TxQuantize.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="TxReSample.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="TxTexCache.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="TxUtil.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath="Ext_TxFilter.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="Internal.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="TextureFilters.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="TextureFilters_2xsai.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="TextureFilters_hq2x.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="TextureFilters_hq4x.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="TextureFilters_lq2x.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="TxCache.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="TxDbg.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="TxFilter.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="TxHiResCache.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="TxImage.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="TxQuantize.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="TxTexCache.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="TxUtil.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="tc-1.1+"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\tc-1.1+\dxtn.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\tc-1.1+\fxt1.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\tc-1.1+\fxt1.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\tc-1.1+\internal.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\tc-1.1+\texstore.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\tc-1.1+\types.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\tc-1.1+\wrapper.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* GlideHQ (Texture enhancer library for Glide64)
|
||||
* Version: 1.5
|
||||
*
|
||||
* Copyright (C) 2007 Hiroshi Morii aka KoolSmoky All Rights Reserved.
|
||||
* Email koolsmoky(at)users.sourceforge.net
|
||||
* Web http://www.3dfxzone.it/koolsmoky
|
||||
*
|
||||
* this 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* this 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
About:
|
||||
This is a realtime texture enhancer library with hi-resolution texture
|
||||
pack support for Glide64 (http://glide64.emuxhaven.net). Traditional and
|
||||
non-traditional techniques have been used to achieve speed and high image
|
||||
quality even on a 9 year old 3Dfx Voodoo2.
|
||||
|
||||
Although the 3Dfx Glide3x texture format naming conventions are used, the
|
||||
library can be expanded for generic use.
|
||||
|
||||
Supported:
|
||||
OS: 32bit Linux and MS Windows
|
||||
Enhancers: Hq4x, Hq2x, Hq2xS, Lq2x, Lq2xS, Super2xSai, x2
|
||||
Filters: Smooth (1,2,3,4), Sharp (1,2)
|
||||
Compressors: FXT1, S3TC
|
||||
Input formats: GR_TEXFMT_ALPHA_8,
|
||||
GR_TEXFMT_RGB_565,
|
||||
GR_TEXFMT_ARGB_1555,
|
||||
GR_TEXFMT_ARGB_4444,
|
||||
GR_TEXFMT_ARGB_8888,
|
||||
GR_TEXFMT_ALPHA_INTENSITY_44,
|
||||
GR_TEXFMT_ALPHA_INTENSITY_88
|
||||
Output formats: Same as input unless compression or hires packs are used.
|
||||
Hires texture packs: Rice format (Jabo and GlideHQ format coming later)
|
||||
|
||||
Acknowledgments:
|
||||
I hope you enjoy GlideHQ (texture enhancer library for Glide64). Greatest
|
||||
thanks to Gonetz for making this happen in his busy time. We've rushed
|
||||
everything to share the eye-candy with all of you N64 emulation fans. I
|
||||
would also like to thank a great friend of mine, Daniel Borca for providing
|
||||
the texture compression code, Maxim Stepin (hq2x 4x), and Derek Liauw Kie Fa
|
||||
(2xSaI) for the filtering engines, Rice for his N64 graphics plugin source
|
||||
code, and Mudlord for the hq2xS lq2xS code. GlideHQ also uses the boost C++
|
||||
libraries, zlib general purpose compression library, and the Portable Network
|
||||
Graphics library. Thanks to all the developers for making them available. And
|
||||
special thanks to the Glide64 beta testing crew. Without their feedbacks
|
||||
this library would not have seen daylight. Thank you all.
|
||||
|
||||
The source code for GlideHQ is released in hopes that it will be improved.
|
||||
I know the coding is not on par after so much late night caffeine boosts.
|
||||
If you have suggestions or modifications, please feel free to post them on
|
||||
the Glide64 forum at emuxhaven.
|
||||
|
||||
Porting the library to other platforms should not be so hard. The coding is
|
||||
done with cross platform compatibility in mind and will build with GCC and
|
||||
GNU make. Currently supported are 32bit Linux and MS Windows.
|
||||
|
||||
If you are looking for driver updates for your 3Dfx Interactive Inc. gfx
|
||||
card, grab them from the forums at http://www.3dfxzone.it/enboard/
|
||||
Unbelievable as it seems, drivers are still being updated after 6 years
|
||||
from 3Dfx's demise.
|
||||
|
||||
I know N64 rules, anyone up for PSX? :))
|
||||
|
||||
-KoolSmoky
|
||||
|
||||
References:
|
||||
[1] R.W. Floyd & L. Steinberg, An adaptive algorithm for spatial grey scale,
|
||||
Proceedings of the Society of Information Display 17, pp75-77, 1976
|
||||
[2] Ken Turkowski, Filters for Common Resampling Tasks, Apple Computer 1990
|
||||
http://www.worldserver.com/turk/computergraphics/ResamplingFilters.pdf
|
||||
[3] Don P. Mitchell and Arun N. Netravali, Reconstruction Filters in Computer
|
||||
Graphics, SIGGRAPH '88, Proceedings of the 15th annual conference on
|
||||
Computer graphics and interactive techniques, pp221-228, 1988
|
||||
[4] J. F. Kaiser and W. A. Reed, Data smoothing using low-pass digital
|
||||
filters, Rev. Sci. instrum. 48 (11), pp1447-1457, 1977
|
||||
[5] Maxim Stepin, hq4x Magnification Filter, http://www.hiend3d.com/hq4x.html
|
||||
[6] Derek Liauw Kie Fa, 2xSaI, http://elektron.its.tudelft.nl/~dalikifa
|
||||
[7] Dirk Stevens, Eagle engine http://www.retrofx.com/rfxtech.html
|
||||
[8] 3DFX_texture_compression_FXT1 and EXT_texture_compression_s3tc extension
|
||||
specs from the OpenGL Extension Registry. http://oss.sgi.com/projects/
|
||||
ogl-sample/registry/
|
|
@ -0,0 +1,715 @@
|
|||
/*
|
||||
Copyright (C) 2003 Rice1964
|
||||
|
||||
This program 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.
|
||||
|
||||
This program 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.
|
||||
|
||||
*/
|
||||
|
||||
/* Copyright (C) 2007 Hiroshi Morii <koolsmoky(at)users.sourceforge.net>
|
||||
* Modified for the Texture Filtering library
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "TextureFilters.h"
|
||||
|
||||
/************************************************************************/
|
||||
/* 2X filters */
|
||||
/************************************************************************/
|
||||
|
||||
#define DWORD_MAKE(r, g, b, a) ((uint32) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)))
|
||||
#define WORD_MAKE(r, g, b, a) ((uint16) (((a) << 12) | ((r) << 8) | ((g) << 4) | (b)))
|
||||
|
||||
// Basic 2x R8G8B8A8 filter with interpolation
|
||||
|
||||
void Texture2x_32(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height)
|
||||
{
|
||||
uint32 *pDst1, *pDst2;
|
||||
uint32 *pSrc, *pSrc2;
|
||||
uint32 nWidth = width;
|
||||
uint32 nHeight = height;
|
||||
|
||||
uint32 b1;
|
||||
uint32 g1;
|
||||
uint32 r1;
|
||||
uint32 a1;
|
||||
uint32 b2;
|
||||
uint32 g2;
|
||||
uint32 r2;
|
||||
uint32 a2;
|
||||
uint32 b3;
|
||||
uint32 g3;
|
||||
uint32 r3;
|
||||
uint32 a3;
|
||||
uint32 b4;
|
||||
uint32 g4;
|
||||
uint32 r4;
|
||||
uint32 a4;
|
||||
|
||||
uint32 xSrc;
|
||||
uint32 ySrc;
|
||||
|
||||
for (ySrc = 0; ySrc < nHeight; ySrc++)
|
||||
{
|
||||
pSrc = (uint32*)(((uint8*)srcPtr)+ySrc*srcPitch);
|
||||
pSrc2 = (uint32*)(((uint8*)srcPtr)+(ySrc+1)*srcPitch);
|
||||
pDst1 = (uint32*)(((uint8*)dstPtr)+(ySrc*2)*dstPitch);
|
||||
pDst2 = (uint32*)(((uint8*)dstPtr)+(ySrc*2+1)*dstPitch);
|
||||
|
||||
for (xSrc = 0; xSrc < nWidth; xSrc++)
|
||||
{
|
||||
b1 = (pSrc[xSrc]>>0)&0xFF;
|
||||
g1 = (pSrc[xSrc]>>8)&0xFF;
|
||||
r1 = (pSrc[xSrc]>>16)&0xFF;
|
||||
a1 = (pSrc[xSrc]>>24)&0xFF;
|
||||
|
||||
if( xSrc<nWidth-1 )
|
||||
{
|
||||
b2 = (pSrc[xSrc+1]>>0)&0xFF;
|
||||
g2 = (pSrc[xSrc+1]>>8)&0xFF;
|
||||
r2 = (pSrc[xSrc+1]>>16)&0xFF;
|
||||
a2 = (pSrc[xSrc+1]>>24)&0xFF;
|
||||
}
|
||||
|
||||
if( ySrc<nHeight-1 )
|
||||
{
|
||||
b3 = (pSrc2[xSrc]>>0)&0xFF;
|
||||
g3 = (pSrc2[xSrc]>>8)&0xFF;
|
||||
r3 = (pSrc2[xSrc]>>16)&0xFF;
|
||||
a3 = (pSrc2[xSrc]>>24)&0xFF;
|
||||
if( xSrc<nWidth-1 )
|
||||
{
|
||||
b4 = (pSrc2[xSrc+1]>>0)&0xFF;
|
||||
g4 = (pSrc2[xSrc+1]>>8)&0xFF;
|
||||
r4 = (pSrc2[xSrc+1]>>16)&0xFF;
|
||||
a4 = (pSrc2[xSrc+1]>>24)&0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Pixel 1
|
||||
pDst1[xSrc*2] = pSrc[xSrc];
|
||||
|
||||
// Pixel 2
|
||||
if( xSrc<nWidth-1 )
|
||||
{
|
||||
pDst1[xSrc*2+1] = DWORD_MAKE((r1+r2)/2, (g1+g2)/2, (b1+b2)/2, (a1+a2)/2);
|
||||
}
|
||||
else
|
||||
pDst1[xSrc*2+1] = pSrc[xSrc];
|
||||
|
||||
|
||||
// Pixel 3
|
||||
if( ySrc<nHeight-1 )
|
||||
{
|
||||
pDst2[xSrc*2] = DWORD_MAKE((r1+r3)/2, (g1+g3)/2, (b1+b3)/2, (a1+a3)/2);
|
||||
}
|
||||
else
|
||||
pDst2[xSrc*2] = pSrc[xSrc];
|
||||
|
||||
// Pixel 4
|
||||
if( xSrc<nWidth-1 )
|
||||
{
|
||||
if( ySrc<nHeight-1 )
|
||||
{
|
||||
pDst2[xSrc*2+1] = DWORD_MAKE((r1+r2+r3+r4)/4, (g1+g2+g3+g4)/4, (b1+b2+b3+b4)/4, (a1+a2+a3+a4)/4);
|
||||
}
|
||||
else
|
||||
{
|
||||
pDst2[xSrc*2+1] = DWORD_MAKE((r1+r2)/2, (g1+g2)/2, (b1+b2)/2, (a1+a2)/2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( ySrc<nHeight-1 )
|
||||
{
|
||||
pDst2[xSrc*2+1] = DWORD_MAKE((r1+r3)/2, (g1+g3)/2, (b1+b3)/2, (a1+a3)/2);
|
||||
}
|
||||
else
|
||||
pDst2[xSrc*2+1] = pSrc[xSrc];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !_16BPP_HACK
|
||||
// Basic 2x R4G4B4A4 filter with interpolation
|
||||
void Texture2x_16(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height)
|
||||
{
|
||||
uint16 *pDst1, *pDst2;
|
||||
uint16 *pSrc, *pSrc2;
|
||||
uint32 nWidth = width;
|
||||
uint32 nHeight = height;
|
||||
|
||||
uint16 b1;
|
||||
uint16 g1;
|
||||
uint16 r1;
|
||||
uint16 a1;
|
||||
uint16 b2;
|
||||
uint16 g2;
|
||||
uint16 r2;
|
||||
uint16 a2;
|
||||
uint16 b3;
|
||||
uint16 g3;
|
||||
uint16 r3;
|
||||
uint16 a3;
|
||||
uint16 b4;
|
||||
uint16 g4;
|
||||
uint16 r4;
|
||||
uint16 a4;
|
||||
|
||||
uint16 xSrc;
|
||||
uint16 ySrc;
|
||||
|
||||
for (ySrc = 0; ySrc < nHeight; ySrc++)
|
||||
{
|
||||
pSrc = (uint16*)(((uint8*)srcPtr)+ySrc*srcPitch);
|
||||
pSrc2 = (uint16*)(((uint8*)srcPtr)+(ySrc+1)*srcPitch);
|
||||
pDst1 = (uint16*)(((uint8*)dstPtr)+(ySrc*2)*dstPitch);
|
||||
pDst2 = (uint16*)(((uint8*)dstPtr)+(ySrc*2+1)*dstPitch);
|
||||
|
||||
for (xSrc = 0; xSrc < nWidth; xSrc++)
|
||||
{
|
||||
b1 = (pSrc[xSrc]>> 0)&0xF;
|
||||
g1 = (pSrc[xSrc]>> 4)&0xF;
|
||||
r1 = (pSrc[xSrc]>> 8)&0xF;
|
||||
a1 = (pSrc[xSrc]>>12)&0xF;
|
||||
|
||||
if( xSrc<nWidth-1 )
|
||||
{
|
||||
b2 = (pSrc[xSrc+1]>> 0)&0xF;
|
||||
g2 = (pSrc[xSrc+1]>> 4)&0xF;
|
||||
r2 = (pSrc[xSrc+1]>> 8)&0xF;
|
||||
a2 = (pSrc[xSrc+1]>>12)&0xF;
|
||||
}
|
||||
|
||||
if( ySrc<nHeight-1 )
|
||||
{
|
||||
b3 = (pSrc2[xSrc]>> 0)&0xF;
|
||||
g3 = (pSrc2[xSrc]>> 4)&0xF;
|
||||
r3 = (pSrc2[xSrc]>> 8)&0xF;
|
||||
a3 = (pSrc2[xSrc]>>12)&0xF;
|
||||
if( xSrc<nWidth-1 )
|
||||
{
|
||||
b4 = (pSrc2[xSrc+1]>> 0)&0xF;
|
||||
g4 = (pSrc2[xSrc+1]>> 4)&0xF;
|
||||
r4 = (pSrc2[xSrc+1]>> 8)&0xF;
|
||||
a4 = (pSrc2[xSrc+1]>>12)&0xF;
|
||||
}
|
||||
}
|
||||
|
||||
// Pixel 1
|
||||
pDst1[xSrc*2] = pSrc[xSrc];
|
||||
|
||||
// Pixel 2
|
||||
if( xSrc<nWidth-1 )
|
||||
{
|
||||
pDst1[xSrc*2+1] = WORD_MAKE((r1+r2)/2, (g1+g2)/2, (b1+b2)/2, (a1+a2)/2);
|
||||
}
|
||||
else
|
||||
pDst1[xSrc*2+1] = pSrc[xSrc];
|
||||
|
||||
|
||||
// Pixel 3
|
||||
if( ySrc<nHeight-1 )
|
||||
{
|
||||
pDst2[xSrc*2] = WORD_MAKE((r1+r3)/2, (g1+g3)/2, (b1+b3)/2, (a1+a3)/2);
|
||||
}
|
||||
else
|
||||
pDst2[xSrc*2] = pSrc[xSrc];
|
||||
|
||||
// Pixel 4
|
||||
if( xSrc<nWidth-1 )
|
||||
{
|
||||
if( ySrc<nHeight-1 )
|
||||
{
|
||||
pDst2[xSrc*2+1] = WORD_MAKE((r1+r2+r3+r4)/4, (g1+g2+g3+g4)/4, (b1+b2+b3+b4)/4, (a1+a2+a3+a4)/4);
|
||||
}
|
||||
else
|
||||
{
|
||||
pDst2[xSrc*2+1] = WORD_MAKE((r1+r2)/2, (g1+g2)/2, (b1+b2)/2, (a1+a2)/2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( ySrc<nHeight-1 )
|
||||
{
|
||||
pDst2[xSrc*2+1] = WORD_MAKE((r1+r3)/2, (g1+g3)/2, (b1+b3)/2, (a1+a3)/2);
|
||||
}
|
||||
else
|
||||
pDst2[xSrc*2+1] = pSrc[xSrc];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* !_16BPP_HACK */
|
||||
|
||||
/*
|
||||
* Sharp filters
|
||||
* Hiroshi Morii <koolsmoky@users.sourceforge.net>
|
||||
*/
|
||||
void SharpFilter_8888(uint32 *src, uint32 srcwidth, uint32 srcheight, uint32 *dest, uint32 filter)
|
||||
{
|
||||
// NOTE: for now we get away with copying the boundaries
|
||||
// filter the boundaries if we face problems
|
||||
|
||||
uint32 mul1, mul2, mul3, shift4;
|
||||
|
||||
uint32 x,y,z;
|
||||
uint32 *_src1, *_src2, *_src3, *_dest;
|
||||
uint32 val[4];
|
||||
uint32 t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
|
||||
switch( filter )
|
||||
{
|
||||
case SHARP_FILTER_2:
|
||||
mul1=1;
|
||||
mul2=8;
|
||||
mul3=12;
|
||||
shift4=2;
|
||||
break;
|
||||
case SHARP_FILTER_1:
|
||||
default:
|
||||
mul1=1;
|
||||
mul2=8;
|
||||
mul3=16;
|
||||
shift4=3;
|
||||
break;
|
||||
}
|
||||
|
||||
// setup rows
|
||||
_src1 = src;
|
||||
_src2 = _src1 + srcwidth;
|
||||
_src3 = _src2 + srcwidth;
|
||||
_dest = dest;
|
||||
|
||||
// copy the first row
|
||||
memcpy(_dest, _src1, (srcwidth << 2));
|
||||
_dest += srcwidth;
|
||||
// filter 2nd row to 1 row before the last
|
||||
for (y = 1; y < srcheight-1; y++) {
|
||||
// copy the first pixel
|
||||
_dest[0] = *_src2;
|
||||
// filter 2nd pixel to 1 pixel before last
|
||||
for (x = 1; x < srcwidth-1; x++) {
|
||||
for (z=0; z<4; z++) {
|
||||
t1 = *((uint8*)(_src1+x-1)+z);
|
||||
t2 = *((uint8*)(_src1+x )+z);
|
||||
t3 = *((uint8*)(_src1+x+1)+z);
|
||||
t4 = *((uint8*)(_src2+x-1)+z);
|
||||
t5 = *((uint8*)(_src2+x )+z);
|
||||
t6 = *((uint8*)(_src2+x+1)+z);
|
||||
t7 = *((uint8*)(_src3+x-1)+z);
|
||||
t8 = *((uint8*)(_src3+x )+z);
|
||||
t9 = *((uint8*)(_src3+x+1)+z);
|
||||
|
||||
if( (t5*mul2) > (t1+t3+t7+t9+t2+t4+t6+t8)*mul1 ) {
|
||||
val[z]= ((t5*mul3) - (t1+t3+t7+t9+t2+t4+t6+t8)*mul1)>>shift4;
|
||||
if (val[z] > 0xFF) val[z] = 0xFF;
|
||||
} else {
|
||||
val[z] = t5;
|
||||
}
|
||||
}
|
||||
_dest[x] = val[0]|(val[1]<<8)|(val[2]<<16)|(val[3]<<24);
|
||||
}
|
||||
// copy the ending pixel
|
||||
_dest[srcwidth-1] = *(_src3 - 1);
|
||||
// next row
|
||||
_src1 += srcwidth;
|
||||
_src2 += srcwidth;
|
||||
_src3 += srcwidth;
|
||||
_dest += srcwidth;
|
||||
}
|
||||
// copy the last row
|
||||
memcpy(_dest, _src2, (srcwidth << 2));
|
||||
}
|
||||
|
||||
#if !_16BPP_HACK
|
||||
void SharpFilter_4444(uint16 *src, uint32 srcwidth, uint32 srcheight, uint16 *dest, uint32 filter)
|
||||
{
|
||||
// NOTE: for now we get away with copying the boundaries
|
||||
// filter the boundaries if we face problems
|
||||
|
||||
uint16 mul1, mul2, mul3, shift4;
|
||||
|
||||
uint32 x,y,z;
|
||||
uint16 *_src1, *_src2, *_src3, *_dest;
|
||||
uint16 val[4];
|
||||
uint16 t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
|
||||
switch( filter ) {
|
||||
case SHARP_FILTER_2:
|
||||
mul1=1;
|
||||
mul2=8;
|
||||
mul3=12;
|
||||
shift4=2;
|
||||
break;
|
||||
case SHARP_FILTER_1:
|
||||
default:
|
||||
mul1=1;
|
||||
mul2=8;
|
||||
mul3=16;
|
||||
shift4=3;
|
||||
break;
|
||||
}
|
||||
|
||||
// setup rows
|
||||
_src1 = src;
|
||||
_src2 = _src1 + srcwidth;
|
||||
_src3 = _src2 + srcwidth;
|
||||
_dest = dest;
|
||||
|
||||
// copy the first row
|
||||
memcpy(_dest, _src1, (srcwidth << 1));
|
||||
_dest += srcwidth;
|
||||
// filter 2nd row to 1 row before the last
|
||||
for( y = 1; y < srcheight - 1; y++) {
|
||||
// copy the first pixel
|
||||
_dest[0] = *_src2;
|
||||
// filter 2nd pixel to 1 pixel before last
|
||||
for( x = 1; x < srcwidth - 1; x++) {
|
||||
for( z = 0; z < 4; z++ ) {
|
||||
/* Hiroshi Morii <koolsmoky@users.sourceforge.net>
|
||||
* Read the entire 16bit pixel and then extract the A,R,G,B components.
|
||||
*/
|
||||
uint32 shift = z << 2;
|
||||
t1 = ((*((uint16*)(_src1+x-1))) >> shift) & 0xF;
|
||||
t2 = ((*((uint16*)(_src1+x ))) >> shift) & 0xF;
|
||||
t3 = ((*((uint16*)(_src1+x+1))) >> shift) & 0xF;
|
||||
t4 = ((*((uint16*)(_src2+x-1))) >> shift) & 0xF;
|
||||
t5 = ((*((uint16*)(_src2+x ))) >> shift) & 0xF;
|
||||
t6 = ((*((uint16*)(_src2+x+1))) >> shift) & 0xF;
|
||||
t7 = ((*((uint16*)(_src3+x-1))) >> shift) & 0xF;
|
||||
t8 = ((*((uint16*)(_src3+x ))) >> shift) & 0xF;
|
||||
t9 = ((*((uint16*)(_src3+x+1))) >> shift) & 0xF;
|
||||
|
||||
if( (t5*mul2) > (t1+t3+t7+t9+t2+t4+t6+t8)*mul1 ) {
|
||||
val[z] = ((t5*mul3) - (t1+t3+t7+t9+t2+t4+t6+t8)*mul1)>>shift4;
|
||||
if (val[z] > 0xF) val[z] = 0xF;
|
||||
} else {
|
||||
val[z] = t5;
|
||||
}
|
||||
}
|
||||
_dest[x] = val[0]|(val[1]<<4)|(val[2]<<8)|(val[3]<<12);
|
||||
}
|
||||
// copy the ending pixel
|
||||
_dest[srcwidth-1] = *(_src3 - 1);
|
||||
// next row
|
||||
_src1 += srcwidth;
|
||||
_src2 += srcwidth;
|
||||
_src3 += srcwidth;
|
||||
_dest += srcwidth;
|
||||
}
|
||||
// copy the last row
|
||||
memcpy(_dest, _src2, (srcwidth << 1));
|
||||
}
|
||||
#endif /* !_16BPP_HACK */
|
||||
|
||||
/*
|
||||
* Smooth filters
|
||||
* Hiroshi Morii <koolsmoky@users.sourceforge.net>
|
||||
*/
|
||||
void SmoothFilter_8888(uint32 *src, uint32 srcwidth, uint32 srcheight, uint32 *dest, uint32 filter)
|
||||
{
|
||||
// NOTE: for now we get away with copying the boundaries
|
||||
// filter the boundaries if we face problems
|
||||
|
||||
uint32 mul1, mul2, mul3, shift4;
|
||||
|
||||
uint32 x,y,z;
|
||||
uint32 *_src1, *_src2, *_src3, *_dest;
|
||||
uint32 val[4];
|
||||
uint32 t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
|
||||
switch( filter ) {
|
||||
case SMOOTH_FILTER_4:
|
||||
mul1=1;
|
||||
mul2=2;
|
||||
mul3=4;
|
||||
shift4=4;
|
||||
break;
|
||||
case SMOOTH_FILTER_3:
|
||||
mul1=1;
|
||||
mul2=1;
|
||||
mul3=8;
|
||||
shift4=4;
|
||||
break;
|
||||
case SMOOTH_FILTER_2:
|
||||
mul1=1;
|
||||
mul2=1;
|
||||
mul3=2;
|
||||
shift4=2;
|
||||
break;
|
||||
case SMOOTH_FILTER_1:
|
||||
default:
|
||||
mul1=1;
|
||||
mul2=1;
|
||||
mul3=6;
|
||||
shift4=3;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (filter) {
|
||||
case SMOOTH_FILTER_3:
|
||||
case SMOOTH_FILTER_4:
|
||||
// setup rows
|
||||
_src1 = src;
|
||||
_src2 = _src1 + srcwidth;
|
||||
_src3 = _src2 + srcwidth;
|
||||
_dest = dest;
|
||||
// copy the first row
|
||||
memcpy(_dest, _src1, (srcwidth << 2));
|
||||
_dest += srcwidth;
|
||||
// filter 2nd row to 1 row before the last
|
||||
for (y = 1; y < srcheight - 1; y++){
|
||||
// copy the first pixel
|
||||
_dest[0] = _src2[0];
|
||||
// filter 2nd pixel to 1 pixel before last
|
||||
for (x = 1; x < srcwidth - 1; x++) {
|
||||
for (z = 0; z < 4; z++ ) {
|
||||
t1 = *((uint8*)(_src1+x-1)+z);
|
||||
t2 = *((uint8*)(_src1+x )+z);
|
||||
t3 = *((uint8*)(_src1+x+1)+z);
|
||||
t4 = *((uint8*)(_src2+x-1)+z);
|
||||
t5 = *((uint8*)(_src2+x )+z);
|
||||
t6 = *((uint8*)(_src2+x+1)+z);
|
||||
t7 = *((uint8*)(_src3+x-1)+z);
|
||||
t8 = *((uint8*)(_src3+x )+z);
|
||||
t9 = *((uint8*)(_src3+x+1)+z);
|
||||
/* the component value must not overflow 0xFF */
|
||||
val[z] = ((t1+t3+t7+t9)*mul1+((t2+t4+t6+t8)*mul2)+(t5*mul3))>>shift4;
|
||||
if (val[z] > 0xFF) val[z] = 0xFF;
|
||||
}
|
||||
_dest[x] = val[0]|(val[1]<<8)|(val[2]<<16)|(val[3]<<24);
|
||||
}
|
||||
// copy the ending pixel
|
||||
_dest[srcwidth-1] = *(_src3 - 1);
|
||||
// next row
|
||||
_src1 += srcwidth;
|
||||
_src2 += srcwidth;
|
||||
_src3 += srcwidth;
|
||||
_dest += srcwidth;
|
||||
}
|
||||
// copy the last row
|
||||
memcpy(_dest, _src2, (srcwidth << 2));
|
||||
break;
|
||||
case SMOOTH_FILTER_1:
|
||||
case SMOOTH_FILTER_2:
|
||||
default:
|
||||
// setup rows
|
||||
_src1 = src;
|
||||
_src2 = _src1 + srcwidth;
|
||||
_src3 = _src2 + srcwidth;
|
||||
_dest = dest;
|
||||
// copy the first row
|
||||
memcpy(_dest, _src1, (srcwidth << 2));
|
||||
_dest += srcwidth;
|
||||
// filter 2nd row to 1 row before the last
|
||||
for (y = 1; y < srcheight - 1; y++) {
|
||||
// filter 1st pixel to the last
|
||||
if (y & 1) {
|
||||
for( x = 0; x < srcwidth; x++) {
|
||||
for( z = 0; z < 4; z++ ) {
|
||||
t2 = *((uint8*)(_src1+x )+z);
|
||||
t5 = *((uint8*)(_src2+x )+z);
|
||||
t8 = *((uint8*)(_src3+x )+z);
|
||||
/* the component value must not overflow 0xFF */
|
||||
val[z] = ((t2+t8)*mul2+(t5*mul3))>>shift4;
|
||||
if (val[z] > 0xFF) val[z] = 0xFF;
|
||||
}
|
||||
_dest[x] = val[0]|(val[1]<<8)|(val[2]<<16)|(val[3]<<24);
|
||||
}
|
||||
} else {
|
||||
memcpy(_dest, _src2, (srcwidth << 2));
|
||||
}
|
||||
// next row
|
||||
_src1 += srcwidth;
|
||||
_src2 += srcwidth;
|
||||
_src3 += srcwidth;
|
||||
_dest += srcwidth;
|
||||
}
|
||||
// copy the last row
|
||||
memcpy(_dest, _src2, (srcwidth << 2));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if !_16BPP_HACK
|
||||
void SmoothFilter_4444(uint16 *src, uint32 srcwidth, uint32 srcheight, uint16 *dest, uint32 filter)
|
||||
{
|
||||
// NOTE: for now we get away with copying the boundaries
|
||||
// filter the boundaries if we face problems
|
||||
|
||||
uint16 mul1, mul2, mul3, shift4;
|
||||
|
||||
uint32 x,y,z;
|
||||
uint16 *_src1, *_src2, *_src3, *_dest;
|
||||
uint16 val[4];
|
||||
uint16 t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
|
||||
switch( filter ) {
|
||||
case SMOOTH_FILTER_4:
|
||||
mul1=1;
|
||||
mul2=2;
|
||||
mul3=4;
|
||||
shift4=4;
|
||||
break;
|
||||
case SMOOTH_FILTER_3:
|
||||
mul1=1;
|
||||
mul2=1;
|
||||
mul3=8;
|
||||
shift4=4;
|
||||
break;
|
||||
case SMOOTH_FILTER_2:
|
||||
mul1=1;
|
||||
mul2=1;
|
||||
mul3=2;
|
||||
shift4=2;
|
||||
break;
|
||||
case SMOOTH_FILTER_1:
|
||||
default:
|
||||
mul1=1;
|
||||
mul2=1;
|
||||
mul3=6;
|
||||
shift4=3;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (filter) {
|
||||
case SMOOTH_FILTER_3:
|
||||
case SMOOTH_FILTER_4:
|
||||
// setup rows
|
||||
_src1 = src;
|
||||
_src2 = _src1 + srcwidth;
|
||||
_src3 = _src2 + srcwidth;
|
||||
_dest = dest;
|
||||
// copy the first row
|
||||
memcpy(_dest, _src1, (srcwidth << 1));
|
||||
_dest += srcwidth;
|
||||
// filter 2nd row to 1 row before the last
|
||||
for (y = 1; y < srcheight - 1; y++) {
|
||||
// copy the first pixel
|
||||
_dest[0] = *_src2;
|
||||
// filter 2nd pixel to 1 pixel before last
|
||||
for (x = 1; x < srcwidth - 1; x++) {
|
||||
for (z = 0; z < 4; z++ ) {
|
||||
/* Read the entire 16bit pixel and then extract the A,R,G,B components. */
|
||||
uint32 shift = z << 2;
|
||||
t1 = ((*(uint16*)(_src1+x-1)) >> shift) & 0xF;
|
||||
t2 = ((*(uint16*)(_src1+x )) >> shift) & 0xF;
|
||||
t3 = ((*(uint16*)(_src1+x+1)) >> shift) & 0xF;
|
||||
t4 = ((*(uint16*)(_src2+x-1)) >> shift) & 0xF;
|
||||
t5 = ((*(uint16*)(_src2+x )) >> shift) & 0xF;
|
||||
t6 = ((*(uint16*)(_src2+x+1)) >> shift) & 0xF;
|
||||
t7 = ((*(uint16*)(_src3+x-1)) >> shift) & 0xF;
|
||||
t8 = ((*(uint16*)(_src3+x )) >> shift) & 0xF;
|
||||
t9 = ((*(uint16*)(_src3+x+1)) >> shift) & 0xF;
|
||||
/* the component value must not overflow 0xF */
|
||||
val[z] = ((t1+t3+t7+t9)*mul1+((t2+t4+t6+t8)*mul2)+(t5*mul3))>>shift4;
|
||||
if (val[z] > 0xF) val[z] = 0xF;
|
||||
}
|
||||
_dest[x] = val[0]|(val[1]<<4)|(val[2]<<8)|(val[3]<<12);
|
||||
}
|
||||
// copy the ending pixel
|
||||
_dest[srcwidth-1] = *(_src3 - 1);
|
||||
// next row
|
||||
_src1 += srcwidth;
|
||||
_src2 += srcwidth;
|
||||
_src3 += srcwidth;
|
||||
_dest += srcwidth;
|
||||
}
|
||||
// copy the last row
|
||||
memcpy(_dest, _src2, (srcwidth << 1));
|
||||
break;
|
||||
case SMOOTH_FILTER_1:
|
||||
case SMOOTH_FILTER_2:
|
||||
default:
|
||||
// setup rows
|
||||
_src1 = src;
|
||||
_src2 = _src1 + srcwidth;
|
||||
_src3 = _src2 + srcwidth;
|
||||
_dest = dest;
|
||||
// copy the first row
|
||||
memcpy(_dest, _src1, (srcwidth << 1));
|
||||
_dest += srcwidth;
|
||||
// filter 2nd row to 1 row before the last
|
||||
for( y = 1; y < srcheight - 1; y++) {
|
||||
if (y & 1) {
|
||||
for( x = 0; x < srcwidth; x++) {
|
||||
for( z = 0; z < 4; z++ ) {
|
||||
/* Read the entire 16bit pixel and then extract the A,R,G,B components. */
|
||||
uint32 shift = z << 2;
|
||||
t2 = ((*(uint16*)(_src1+x)) >> shift) & 0xF;
|
||||
t5 = ((*(uint16*)(_src2+x)) >> shift) & 0xF;
|
||||
t8 = ((*(uint16*)(_src3+x)) >> shift) & 0xF;
|
||||
/* the component value must not overflow 0xF */
|
||||
val[z] = ((t2+t8)*mul2+(t5*mul3))>>shift4;
|
||||
if (val[z] > 0xF) val[z] = 0xF;
|
||||
}
|
||||
_dest[x] = val[0]|(val[1]<<4)|(val[2]<<8)|(val[3]<<12);
|
||||
}
|
||||
} else {
|
||||
memcpy(_dest, _src2, (srcwidth << 1));
|
||||
}
|
||||
// next row
|
||||
_src1 += srcwidth;
|
||||
_src2 += srcwidth;
|
||||
_src3 += srcwidth;
|
||||
_dest += srcwidth;
|
||||
}
|
||||
// copy the last row
|
||||
memcpy(_dest, _src2, (srcwidth << 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* !_16BPP_HACK */
|
||||
|
||||
void filter_8888(uint32 *src, uint32 srcwidth, uint32 srcheight, uint32 *dest, uint32 filter) {
|
||||
switch (filter & ENHANCEMENT_MASK) {
|
||||
case HQ4X_ENHANCEMENT:
|
||||
hq4x_8888((uint8*)src, (uint8*)dest, srcwidth, srcheight, srcwidth, (srcwidth << 4));
|
||||
return;
|
||||
case HQ2X_ENHANCEMENT:
|
||||
hq2x_32((uint8*)src, (srcwidth << 2), (uint8*)dest, (srcwidth << 3), srcwidth, srcheight);
|
||||
return;
|
||||
case HQ2XS_ENHANCEMENT:
|
||||
hq2xS_32((uint8*)src, (srcwidth << 2), (uint8*)dest, (srcwidth << 3), srcwidth, srcheight);
|
||||
return;
|
||||
case LQ2X_ENHANCEMENT:
|
||||
lq2x_32((uint8*)src, (srcwidth << 2), (uint8*)dest, (srcwidth << 3), srcwidth, srcheight);
|
||||
return;
|
||||
case LQ2XS_ENHANCEMENT:
|
||||
lq2xS_32((uint8*)src, (srcwidth << 2), (uint8*)dest, (srcwidth << 3), srcwidth, srcheight);
|
||||
return;
|
||||
case X2SAI_ENHANCEMENT:
|
||||
Super2xSaI_8888((uint32*)src, (uint32*)dest, srcwidth, srcheight, srcwidth);
|
||||
return;
|
||||
case X2_ENHANCEMENT:
|
||||
Texture2x_32((uint8*)src, (srcwidth << 2), (uint8*)dest, (srcwidth << 3), srcwidth, srcheight);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (filter & (SMOOTH_FILTER_MASK|SHARP_FILTER_MASK)) {
|
||||
case SMOOTH_FILTER_1:
|
||||
case SMOOTH_FILTER_2:
|
||||
case SMOOTH_FILTER_3:
|
||||
case SMOOTH_FILTER_4:
|
||||
SmoothFilter_8888((uint32*)src, srcwidth, srcheight, (uint32*)dest, (filter & SMOOTH_FILTER_MASK));
|
||||
return;
|
||||
case SHARP_FILTER_1:
|
||||
case SHARP_FILTER_2:
|
||||
SharpFilter_8888((uint32*)src, srcwidth, srcheight, (uint32*)dest, (filter & SHARP_FILTER_MASK));
|
||||
return;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Texture Filtering
|
||||
* Version: 1.0
|
||||
*
|
||||
* Copyright (C) 2007 Hiroshi Morii All Rights Reserved.
|
||||
* Email koolsmoky(at)users.sourceforge.net
|
||||
* Web http://www.3dfxzone.it/koolsmoky
|
||||
*
|
||||
* this 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* this 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __TEXTUREFILTERS_H__
|
||||
#define __TEXTUREFILTERS_H__
|
||||
|
||||
/* 16bpp filters are somewhat buggy and output image is not clean.
|
||||
* Since there's not much time, we'll just convert them to ARGB8888
|
||||
* and use 32bpp filters until fixed.
|
||||
* (1:enable hack, 0:disable hack) */
|
||||
#define _16BPP_HACK 1
|
||||
|
||||
#include "TxInternal.h"
|
||||
|
||||
/* enhancers */
|
||||
void hq4x_8888(unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int SrcPPL, int BpL);
|
||||
|
||||
void hq2x_32(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height);
|
||||
void hq2xS_32(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height);
|
||||
|
||||
void lq2x_32(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height);
|
||||
void lq2xS_32(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height);
|
||||
|
||||
void Super2xSaI_8888(uint32 *srcPtr, uint32 *destPtr, uint32 width, uint32 height, uint32 pitch);
|
||||
|
||||
void Texture2x_32(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height);
|
||||
|
||||
/* filters */
|
||||
void SharpFilter_8888(uint32 *src, uint32 srcwidth, uint32 srcheight, uint32 *dest, uint32 filter);
|
||||
|
||||
void SmoothFilter_8888(uint32 *src, uint32 srcwidth, uint32 srcheight, uint32 *dest, uint32 filter);
|
||||
|
||||
/* helper */
|
||||
void filter_8888(uint32 *src, uint32 srcwidth, uint32 srcheight, uint32 *dest, uint32 filter);
|
||||
|
||||
#if !_16BPP_HACK
|
||||
void hq4x_init(void);
|
||||
void hq4x_4444(unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int SrcPPL, int BpL);
|
||||
void hq4x_1555(unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int SrcPPL, int BpL);
|
||||
void hq4x_565 (unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int SrcPPL, int BpL);
|
||||
|
||||
void hq2x_16(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height);
|
||||
void hq2xS_16(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height);
|
||||
|
||||
void lq2x_16(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height);
|
||||
void lq2xS_16(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height);
|
||||
|
||||
void Super2xSaI_4444(uint16 *srcPtr, uint16 *destPtr, uint32 width, uint32 height, uint32 pitch);
|
||||
void Super2xSaI_1555(uint16 *srcPtr, uint16 *destPtr, uint32 width, uint32 height, uint32 pitch);
|
||||
void Super2xSaI_565 (uint16 *srcPtr, uint16 *destPtr, uint32 width, uint32 height, uint32 pitch);
|
||||
void Super2xSaI_8 (uint8 *srcPtr, uint8 *destPtr, uint32 width, uint32 height, uint32 pitch);
|
||||
|
||||
void Texture2x_16(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height);
|
||||
|
||||
void SharpFilter_4444(uint16 *src, uint32 srcwidth, uint32 srcheight, uint16 *dest, uint32 filter);
|
||||
|
||||
void SmoothFilter_4444(uint16 *src, uint32 srcwidth, uint32 srcheight, uint16 *dest, uint32 filter);
|
||||
#endif
|
||||
|
||||
#endif /* __TEXTUREFILTERS_H__ */
|
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* Texture Filtering
|
||||
* Version: 1.0
|
||||
*
|
||||
* Copyright (C) 2007 Hiroshi Morii All Rights Reserved.
|
||||
* Email koolsmoky(at)users.sourceforge.net
|
||||
* Web http://www.3dfxzone.it/koolsmoky
|
||||
*
|
||||
* this 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* this 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/* Based on Derek Liauw Kie Fa and Rice1964 Super2xSaI code */
|
||||
|
||||
#include "TextureFilters.h"
|
||||
|
||||
#define GET_RESULT(A, B, C, D) ((A != C || A != D) - (B != C || B != D))
|
||||
|
||||
void Super2xSaI_8888(uint32 *srcPtr, uint32 *destPtr, uint32 width, uint32 height, uint32 pitch)
|
||||
{
|
||||
#define SAI_INTERPOLATE_8888(A, B) ((A & 0xFEFEFEFE) >> 1) + ((B & 0xFEFEFEFE) >> 1) + (A & B & 0x01010101)
|
||||
#define SAI_Q_INTERPOLATE_8888(A, B, C, D) ((A & 0xFCFCFCFC) >> 2) + ((B & 0xFCFCFCFC) >> 2) + ((C & 0xFCFCFCFC) >> 2) + ((D & 0xFCFCFCFC) >> 2) \
|
||||
+ ((((A & 0x03030303) + (B & 0x03030303) + (C & 0x03030303) + (D & 0x03030303)) >> 2) & 0x03030303)
|
||||
|
||||
#define SAI_INTERPOLATE SAI_INTERPOLATE_8888
|
||||
#define SAI_Q_INTERPOLATE SAI_Q_INTERPOLATE_8888
|
||||
|
||||
uint32 destWidth = width << 1;
|
||||
uint32 destHeight = height << 1;
|
||||
|
||||
uint32 color4, color5, color6;
|
||||
uint32 color1, color2, color3;
|
||||
uint32 colorA0, colorA1, colorA2, colorA3;
|
||||
uint32 colorB0, colorB1, colorB2, colorB3;
|
||||
uint32 colorS1, colorS2;
|
||||
uint32 product1a, product1b, product2a, product2b;
|
||||
|
||||
#include "TextureFilters_2xsai.h"
|
||||
|
||||
#undef SAI_INTERPOLATE
|
||||
#undef SAI_Q_INTERPOLATE
|
||||
}
|
||||
|
||||
#if !_16BPP_HACK
|
||||
void Super2xSaI_4444(uint16 *srcPtr, uint16 *destPtr, uint32 width, uint32 height, uint32 pitch)
|
||||
{
|
||||
#define SAI_INTERPOLATE_4444(A, B) ((A & 0xEEEE) >> 1) + ((B & 0xEEEE) >> 1) + (A & B & 0x1111)
|
||||
#define SAI_Q_INTERPOLATE_4444(A, B, C, D) ((A & 0xCCCC) >> 2) + ((B & 0xCCCC) >> 2) + ((C & 0xCCCC) >> 2) + ((D & 0xCCCC) >> 2) \
|
||||
+ ((((A & 0x3333) + (B & 0x3333) + (C & 0x3333) + (D & 0x3333)) >> 2) & 0x3333)
|
||||
|
||||
#define SAI_INTERPOLATE SAI_INTERPOLATE_4444
|
||||
#define SAI_Q_INTERPOLATE SAI_Q_INTERPOLATE_4444
|
||||
|
||||
uint32 destWidth = width << 1;
|
||||
uint32 destHeight = height << 1;
|
||||
|
||||
uint16 color4, color5, color6;
|
||||
uint16 color1, color2, color3;
|
||||
uint16 colorA0, colorA1, colorA2, colorA3;
|
||||
uint16 colorB0, colorB1, colorB2, colorB3;
|
||||
uint16 colorS1, colorS2;
|
||||
uint16 product1a, product1b, product2a, product2b;
|
||||
|
||||
#include "TextureFilters_2xsai.h"
|
||||
|
||||
#undef SAI_INTERPOLATE
|
||||
#undef SAI_Q_INTERPOLATE
|
||||
}
|
||||
|
||||
void Super2xSaI_1555(uint16 *srcPtr, uint16 *destPtr, uint32 width, uint32 height, uint32 pitch)
|
||||
{
|
||||
#define SAI_INTERPOLATE_1555(A, B) ((A & 0x7BDE) >> 1) + ((B & 0x7BDE) >> 1) + (A & B & 0x8421)
|
||||
#define SAI_Q_INTERPOLATE_1555(A, B, C, D) ((A & 0x739C) >> 2) + ((B & 0x739C) >> 2) + ((C & 0x739C) >> 2) + ((D & 0x739C) >> 2) \
|
||||
+ ((((A & 0x8C63) + (B & 0x8C63) + (C & 0x8C63) + (D & 0x8C63)) >> 2) & 0x8C63)
|
||||
|
||||
#define SAI_INTERPOLATE SAI_INTERPOLATE_1555
|
||||
#define SAI_Q_INTERPOLATE SAI_Q_INTERPOLATE_1555
|
||||
|
||||
uint32 destWidth = width << 1;
|
||||
uint32 destHeight = height << 1;
|
||||
|
||||
uint16 color4, color5, color6;
|
||||
uint16 color1, color2, color3;
|
||||
uint16 colorA0, colorA1, colorA2, colorA3;
|
||||
uint16 colorB0, colorB1, colorB2, colorB3;
|
||||
uint16 colorS1, colorS2;
|
||||
uint16 product1a, product1b, product2a, product2b;
|
||||
|
||||
#include "TextureFilters_2xsai.h"
|
||||
|
||||
#undef SAI_INTERPOLATE
|
||||
#undef SAI_Q_INTERPOLATE
|
||||
}
|
||||
|
||||
void Super2xSaI_565(uint16 *srcPtr, uint16 *destPtr, uint32 width, uint32 height, uint32 pitch)
|
||||
{
|
||||
#define SAI_INTERPOLATE_565(A, B) ((A & 0xF7DE) >> 1) + ((B & 0xF7DE) >> 1) + (A & B & 0x0821)
|
||||
#define SAI_Q_INTERPOLATE_565(A, B, C, D) ((A & 0xE79C) >> 2) + ((B & 0xE79C) >> 2) + ((C & 0xE79C) >> 2) + ((D & 0xE79C) >> 2) \
|
||||
+ ((((A & 0x1863) + (B & 0x1863) + (C & 0x1863) + (D & 0x1863)) >> 2) & 0x1863)
|
||||
|
||||
#define SAI_INTERPOLATE SAI_INTERPOLATE_565
|
||||
#define SAI_Q_INTERPOLATE SAI_Q_INTERPOLATE_565
|
||||
|
||||
uint32 destWidth = width << 1;
|
||||
uint32 destHeight = height << 1;
|
||||
|
||||
uint16 color4, color5, color6;
|
||||
uint16 color1, color2, color3;
|
||||
uint16 colorA0, colorA1, colorA2, colorA3;
|
||||
uint16 colorB0, colorB1, colorB2, colorB3;
|
||||
uint16 colorS1, colorS2;
|
||||
uint16 product1a, product1b, product2a, product2b;
|
||||
|
||||
#include "TextureFilters_2xsai.h"
|
||||
|
||||
#undef SAI_INTERPOLATE
|
||||
#undef SAI_Q_INTERPOLATE
|
||||
}
|
||||
|
||||
void Super2xSaI_8(uint8 *srcPtr, uint8 *destPtr, uint32 width, uint32 height, uint32 pitch)
|
||||
{
|
||||
#define SAI_INTERPOLATE_8(A, B) ((A & 0xFE) >> 1) + ((B & 0xFE) >> 1) + (A & B & 0x01)
|
||||
#define SAI_Q_INTERPOLATE_8(A, B, C, D) ((A & 0xFC) >> 2) + ((B & 0xFC) >> 2) + ((C & 0xFC) >> 2) + ((D & 0xFC) >> 2) \
|
||||
+ ((((A & 0x03) + (B & 0x03) + (C & 0x03) + (D & 0x03)) >> 2) & 0x03)
|
||||
|
||||
#define SAI_INTERPOLATE SAI_INTERPOLATE_8
|
||||
#define SAI_Q_INTERPOLATE SAI_Q_INTERPOLATE_8
|
||||
|
||||
uint32 destWidth = width << 1;
|
||||
uint32 destHeight = height << 1;
|
||||
|
||||
uint8 color4, color5, color6;
|
||||
uint8 color1, color2, color3;
|
||||
uint8 colorA0, colorA1, colorA2, colorA3;
|
||||
uint8 colorB0, colorB1, colorB2, colorB3;
|
||||
uint8 colorS1, colorS2;
|
||||
uint8 product1a, product1b, product2a, product2b;
|
||||
|
||||
#include "TextureFilters_2xsai.h"
|
||||
|
||||
#undef SAI_INTERPOLATE
|
||||
#undef SAI_Q_INTERPOLATE
|
||||
}
|
||||
#endif /* !_16BPP_HACK */
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* Texture Filtering
|
||||
* Version: 1.0
|
||||
*
|
||||
* Copyright (C) 2007 Hiroshi Morii All Rights Reserved.
|
||||
* Email koolsmoky(at)users.sourceforge.net
|
||||
* Web http://www.3dfxzone.it/koolsmoky
|
||||
*
|
||||
* this 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* this 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/* Based on Derek Liauw Kie Fa and Rice1964 Super2xSaI code */
|
||||
|
||||
int row0, row1, row2, row3;
|
||||
int col0, col1, col2, col3;
|
||||
|
||||
uint16 x;
|
||||
uint16 y;
|
||||
|
||||
for (y = 0; y < height; y++) {
|
||||
if ((y > 0) && (y < height - 1)) {
|
||||
row0 = width;
|
||||
row0 = -row0;
|
||||
row1 = 0;
|
||||
row2 = width;
|
||||
row3 = (y == height - 2 ? width : width << 1);
|
||||
} else {
|
||||
row0 = 0;
|
||||
row1 = 0;
|
||||
row2 = 0;
|
||||
row3 = 0;
|
||||
}
|
||||
|
||||
for (x = 0; x < width; x++) {
|
||||
//--------------------------------------- B0 B1 B2 B3
|
||||
// 4 5 6 S2
|
||||
// 1 2 3 S1
|
||||
// A0 A1 A2 A3
|
||||
if ((x > 0) && (x < width - 1)) {
|
||||
col0 = -1;
|
||||
col1 = 0;
|
||||
col2 = 1;
|
||||
col3 = (x == width - 2 ? 1 : 2);
|
||||
} else {
|
||||
col0 = 0;
|
||||
col1 = 0;
|
||||
col2 = 0;
|
||||
col3 = 0;
|
||||
}
|
||||
|
||||
colorB0 = *(srcPtr + col0 + row0);
|
||||
colorB1 = *(srcPtr + col1 + row0);
|
||||
colorB2 = *(srcPtr + col2 + row0);
|
||||
colorB3 = *(srcPtr + col3 + row0);
|
||||
|
||||
color4 = *(srcPtr + col0 + row1);
|
||||
color5 = *(srcPtr + col1 + row1);
|
||||
color6 = *(srcPtr + col2 + row1);
|
||||
colorS2 = *(srcPtr + col3 + row1);
|
||||
|
||||
color1 = *(srcPtr + col0 + row2);
|
||||
color2 = *(srcPtr + col1 + row2);
|
||||
color3 = *(srcPtr + col2 + row2);
|
||||
colorS1 = *(srcPtr + col3 + row2);
|
||||
|
||||
colorA0 = *(srcPtr + col0 + row3);
|
||||
colorA1 = *(srcPtr + col1 + row3);
|
||||
colorA2 = *(srcPtr + col2 + row3);
|
||||
colorA3 = *(srcPtr + col3 + row3);
|
||||
|
||||
//--------------------------------------
|
||||
if (color2 == color6 && color5 != color3)
|
||||
product2b = product1b = color2;
|
||||
else if (color5 == color3 && color2 != color6)
|
||||
product2b = product1b = color5;
|
||||
else if (color5 == color3 && color2 == color6) {
|
||||
int r = 0;
|
||||
|
||||
r += GET_RESULT(color6, color5, color1, colorA1);
|
||||
r += GET_RESULT(color6, color5, color4, colorB1);
|
||||
r += GET_RESULT(color6, color5, colorA2, colorS1);
|
||||
r += GET_RESULT(color6, color5, colorB2, colorS2);
|
||||
|
||||
if (r > 0)
|
||||
product2b = product1b = color6;
|
||||
else if (r < 0)
|
||||
product2b = product1b = color5;
|
||||
else
|
||||
product2b = product1b = SAI_INTERPOLATE(color5, color6);
|
||||
|
||||
} else {
|
||||
|
||||
if (color6 == color3 && color3 == colorA1 && color2 != colorA2 && color3 != colorA0)
|
||||
product2b = SAI_Q_INTERPOLATE(color3, color3, color3, color2);
|
||||
else if (color5 == color2 && color2 == colorA2 && colorA1 != color3 && color2 != colorA3)
|
||||
product2b = SAI_Q_INTERPOLATE(color2, color2, color2, color3);
|
||||
else
|
||||
product2b = SAI_INTERPOLATE(color2, color3);
|
||||
|
||||
if (color6 == color3 && color6 == colorB1 && color5 != colorB2 && color6 != colorB0)
|
||||
product1b = SAI_Q_INTERPOLATE(color6, color6, color6, color5);
|
||||
else if (color5 == color2 && color5 == colorB2 && colorB1 != color6 && color5 != colorB3)
|
||||
product1b = SAI_Q_INTERPOLATE(color6, color5, color5, color5);
|
||||
else
|
||||
product1b = SAI_INTERPOLATE(color5, color6);
|
||||
}
|
||||
|
||||
if (color5 == color3 && color2 != color6 && color4 == color5 && color5 != colorA2)
|
||||
product2a = SAI_INTERPOLATE(color2, color5);
|
||||
else if (color5 == color1 && color6 == color5 && color4 != color2 && color5 != colorA0)
|
||||
product2a = SAI_INTERPOLATE(color2, color5);
|
||||
else
|
||||
product2a = color2;
|
||||
|
||||
if (color2 == color6 && color5 != color3 && color1 == color2 && color2 != colorB2)
|
||||
product1a = SAI_INTERPOLATE(color2, color5);
|
||||
else if (color4 == color2 && color3 == color2 && color1 != color5 && color2 != colorB0)
|
||||
product1a = SAI_INTERPOLATE(color2, color5);
|
||||
else
|
||||
product1a = color5;
|
||||
|
||||
|
||||
destPtr[0] = product1a;
|
||||
destPtr[1] = product1b;
|
||||
destPtr[destWidth] = product2a;
|
||||
destPtr[destWidth + 1] = product2b;
|
||||
|
||||
srcPtr++;
|
||||
destPtr += 2;
|
||||
}
|
||||
srcPtr += (pitch-width);
|
||||
destPtr += (((pitch-width)<<1)+(pitch<<1));
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,892 @@
|
|||
/*
|
||||
* Texture Filtering
|
||||
* Version: 1.0
|
||||
*
|
||||
* Copyright (C) 2007 Hiroshi Morii All Rights Reserved.
|
||||
* Email koolsmoky(at)users.sourceforge.net
|
||||
* Web http://www.3dfxzone.it/koolsmoky
|
||||
*
|
||||
* this 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* this 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/* Based on Maxim Stepin and Rice1964 hq4x code */
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include "TextureFilters.h"
|
||||
|
||||
#if !_16BPP_HACK
|
||||
static uint32 RGB444toYUV[4096];
|
||||
#define RGB444toYUV(val) RGB444toYUV[val & 0x0FFF] /* val = ARGB4444 */
|
||||
|
||||
/*inline static uint32 RGB444toYUV(uint32 val)
|
||||
{
|
||||
uint32 r, g, b, Y, u, v;
|
||||
|
||||
r = (val & 0x0F00) >> 4;
|
||||
g = (val & 0x00F0);
|
||||
b = val & 0x000F;
|
||||
r |= r >> 4;
|
||||
g |= g >> 4;
|
||||
b |= b << 4;
|
||||
|
||||
Y = (r + g + b) >> 2;
|
||||
u = 128 + ((r - b) >> 2);
|
||||
v = 128 + ((2*g - r - b)>>3);
|
||||
|
||||
return ((Y << 16) | (u << 8) | v);
|
||||
}*/
|
||||
|
||||
static uint32 RGB555toYUV(uint32 val)
|
||||
{
|
||||
uint32 r, g, b, Y, u, v;
|
||||
|
||||
r = (val & 0x7C00) >> 7;
|
||||
g = (val & 0x03E0) >> 2;
|
||||
b = (val & 0x001F) << 3;
|
||||
r |= r >> 5;
|
||||
g |= g >> 5;
|
||||
b |= b >> 5;
|
||||
|
||||
Y = (r + g + b) >> 2;
|
||||
u = 128 + ((r - b) >> 2);
|
||||
v = 128 + ((2*g - r - b)>>3);
|
||||
|
||||
return ((Y << 16) | (u << 8) | v);
|
||||
}
|
||||
|
||||
static uint32 RGB565toYUV(uint32 val)
|
||||
{
|
||||
uint32 r, g, b, Y, u, v;
|
||||
|
||||
r = (val & 0xF800) >> 8;
|
||||
g = (val & 0x07E0) >> 3;
|
||||
b = (val & 0x001F) << 3;
|
||||
r |= r >> 5;
|
||||
g |= g >> 6;
|
||||
b |= b >> 5;
|
||||
|
||||
Y = (r + g + b) >> 2;
|
||||
u = 128 + ((r - b) >> 2);
|
||||
v = 128 + ((2*g - r - b)>>3);
|
||||
|
||||
return ((Y << 16) | (u << 8) | v);
|
||||
}
|
||||
#endif /* !_16BPP_HACK */
|
||||
|
||||
static uint32 RGB888toYUV(uint32 val)
|
||||
{
|
||||
#if 0
|
||||
uint32 Yuv;
|
||||
|
||||
__asm {
|
||||
mov eax, dword ptr [val];
|
||||
mov ebx, eax;
|
||||
mov ecx, eax;
|
||||
and ebx, 0x000000ff; // b
|
||||
and eax, 0x00ff0000; // r
|
||||
and ecx, 0x0000ff00; // g
|
||||
shl ebx, 14;
|
||||
shr eax, 2;
|
||||
shl ecx, 6;
|
||||
mov edx, ebx;
|
||||
add edx, eax;
|
||||
add edx, ecx;
|
||||
and edx, 0xffff0000;
|
||||
|
||||
sub eax, ebx;
|
||||
add eax, 0x00800000;
|
||||
shr eax, 8;
|
||||
or edx, eax;
|
||||
sub eax, 0x00800000;
|
||||
and edx, 0xffffff00;
|
||||
|
||||
add ecx, 0x00800000;
|
||||
shr ecx, 5;
|
||||
shr ebx, 7;
|
||||
add eax, ebx;
|
||||
sub ecx, eax;
|
||||
shr ecx, 11;
|
||||
or edx, ecx;
|
||||
|
||||
mov dword ptr [Yuv], edx;
|
||||
}
|
||||
|
||||
return Yuv;
|
||||
#else
|
||||
uint32 r, g, b, Y, u, v;
|
||||
|
||||
r = (val & 0x00ff0000) >> 16;
|
||||
g = (val & 0x0000ff00) >> 8;
|
||||
b = val & 0x000000ff;
|
||||
|
||||
Y = (r + g + b) >> 2;
|
||||
u = (0x00000200 + r - b) >> 2;
|
||||
v = (0x00000400 + (g << 1) - r - b) >> 3;
|
||||
|
||||
return ((Y << 16) | (u << 8) | v);
|
||||
#endif
|
||||
}
|
||||
|
||||
#define Ymask 0x00FF0000
|
||||
#define Umask 0x0000FF00
|
||||
#define Vmask 0x000000FF
|
||||
#define trY 0x00300000 // ?
|
||||
#define trU 0x00000700 // ??
|
||||
#define trV 0x00000006 // ???
|
||||
|
||||
#define HQ4X_INTERP1(n, b) \
|
||||
static void hq4x_Interp1_##n (uint8 * pc, uint##b p1, uint##b p2) \
|
||||
{ \
|
||||
/* *((uint##b*)pc) = (p1*3+p2) >> 2; */ \
|
||||
*((uint##b*)pc) = INTERP_##n##_MASK_1_3((INTERP_##n##_MASK_1_3(p1)*3 + INTERP_##n##_MASK_1_3(p2)) / 4) \
|
||||
| INTERP_##n##_MASK_SHIFTBACK_2_4((INTERP_##n##_MASK_SHIFT_2_4(p1)*3 + INTERP_##n##_MASK_SHIFT_2_4(p2)) / 4 ); \
|
||||
}
|
||||
|
||||
#define HQ4X_INTERP2(n, b) \
|
||||
static void hq4x_Interp2_##n (uint8 * pc, uint##b p1, uint##b p2, uint##b p3) \
|
||||
{ \
|
||||
/**((uint##b*)pc) = (p1*2+p2+p3) >> 2;*/ \
|
||||
*((uint##b*)pc) = INTERP_##n##_MASK_1_3((INTERP_##n##_MASK_1_3(p1)*2 + INTERP_##n##_MASK_1_3(p2) + INTERP_##n##_MASK_1_3(p3)) / 4) \
|
||||
| INTERP_##n##_MASK_SHIFTBACK_2_4((INTERP_##n##_MASK_SHIFT_2_4(p1)*2 + INTERP_##n##_MASK_SHIFT_2_4(p2) + INTERP_##n##_MASK_SHIFT_2_4(p3)) / 4); \
|
||||
}
|
||||
|
||||
#define HQ4X_INTERP3(n, b) \
|
||||
static void hq4x_Interp3_##n (uint8 * pc, uint##b p1, uint##b p2) \
|
||||
{ \
|
||||
/**((uint##b*)pc) = (p1*7+p2)/8;*/ \
|
||||
*((uint##b*)pc) = INTERP_##n##_MASK_1_3((INTERP_##n##_MASK_1_3(p1)*7 + INTERP_##n##_MASK_1_3(p2)) / 8) \
|
||||
| INTERP_##n##_MASK_SHIFTBACK_2_4((INTERP_##n##_MASK_SHIFT_2_4(p1)*7 + INTERP_##n##_MASK_SHIFT_2_4(p2)) / 8); \
|
||||
}
|
||||
|
||||
#define HQ4X_INTERP5(n, b) \
|
||||
static void hq4x_Interp5_##n (uint8 * pc, uint##b p1, uint##b p2) \
|
||||
{ \
|
||||
/**((uint##b*)pc) = (p1+p2) >> 1;*/ \
|
||||
*((uint##b*)pc) = INTERP_##n##_MASK_1_3((INTERP_##n##_MASK_1_3(p1) + INTERP_##n##_MASK_1_3(p2)) / 2) \
|
||||
| INTERP_##n##_MASK_SHIFTBACK_2_4((INTERP_##n##_MASK_SHIFT_2_4(p1) + INTERP_##n##_MASK_SHIFT_2_4(p2)) / 2); \
|
||||
}
|
||||
|
||||
#define HQ4X_INTERP6(n, b) \
|
||||
static void hq4x_Interp6_##n (uint8 * pc, uint##b p1, uint##b p2, uint##b p3) \
|
||||
{ \
|
||||
/**((uint##b*)pc) = (p1*5+p2*2+p3)/8;*/ \
|
||||
*((uint##b*)pc) = INTERP_##n##_MASK_1_3((INTERP_##n##_MASK_1_3(p1)*5 + INTERP_##n##_MASK_1_3(p2)*2 + INTERP_##n##_MASK_1_3(p3)) / 8) \
|
||||
| INTERP_##n##_MASK_SHIFTBACK_2_4((INTERP_##n##_MASK_SHIFT_2_4(p1)*5 + INTERP_##n##_MASK_SHIFT_2_4(p2)*2 + INTERP_##n##_MASK_SHIFT_2_4(p3)) / 8); \
|
||||
}
|
||||
|
||||
#define HQ4X_INTERP7(n, b) \
|
||||
static void hq4x_Interp7_##n (uint8 * pc, uint##b p1, uint##b p2, uint##b p3) \
|
||||
{ \
|
||||
/**((uint##b*)pc) = (p1*6+p2+p3)/8;*/ \
|
||||
*((uint##b*)pc) = INTERP_##n##_MASK_1_3((INTERP_##n##_MASK_1_3(p1)*6 + INTERP_##n##_MASK_1_3(p2) + INTERP_##n##_MASK_1_3(p3)) / 8) \
|
||||
| INTERP_##n##_MASK_SHIFTBACK_2_4((INTERP_##n##_MASK_SHIFT_2_4(p1)*6 + INTERP_##n##_MASK_SHIFT_2_4(p2) + INTERP_##n##_MASK_SHIFT_2_4(p3)) / 8); \
|
||||
}
|
||||
|
||||
#define HQ4X_INTERP8(n, b) \
|
||||
static void hq4x_Interp8_##n (uint8 * pc, uint##b p1, uint##b p2) \
|
||||
{ \
|
||||
/**((uint##b*)pc) = (p1*5+p2*3)/8;*/ \
|
||||
*((uint##b*)pc) = INTERP_##n##_MASK_1_3((INTERP_##n##_MASK_1_3(p1)*5 + INTERP_##n##_MASK_1_3(p2)*3) / 8) \
|
||||
| INTERP_##n##_MASK_SHIFTBACK_2_4((INTERP_##n##_MASK_SHIFT_2_4(p1)*5 + INTERP_##n##_MASK_SHIFT_2_4(p2)*3) / 8); \
|
||||
}
|
||||
|
||||
#if !_16BPP_HACK
|
||||
#define INTERP_4444_MASK_1_3(v) (v & 0x0F0F)
|
||||
#define INTERP_4444_MASK_SHIFT_2_4(v) ((v & 0xF0F0) >> 4)
|
||||
#define INTERP_4444_MASK_SHIFTBACK_2_4(v) (INTERP_4444_MASK_1_3(v) << 4)
|
||||
HQ4X_INTERP1(4444, 16)
|
||||
HQ4X_INTERP2(4444, 16)
|
||||
HQ4X_INTERP3(4444, 16)
|
||||
HQ4X_INTERP5(4444, 16)
|
||||
HQ4X_INTERP6(4444, 16)
|
||||
HQ4X_INTERP7(4444, 16)
|
||||
HQ4X_INTERP8(4444, 16)
|
||||
|
||||
#define INTERP_1555_MASK_1_3(v) (v & 0x7C1F)
|
||||
#define INTERP_1555_MASK_SHIFT_2_4(v) ((v & 0x83E0) >> 5)
|
||||
#define INTERP_1555_MASK_SHIFTBACK_2_4(v) (INTERP_1555_MASK_1_3(v) << 5)
|
||||
HQ4X_INTERP1(1555, 16)
|
||||
HQ4X_INTERP2(1555, 16)
|
||||
HQ4X_INTERP3(1555, 16)
|
||||
HQ4X_INTERP5(1555, 16)
|
||||
HQ4X_INTERP6(1555, 16)
|
||||
HQ4X_INTERP7(1555, 16)
|
||||
HQ4X_INTERP8(1555, 16)
|
||||
|
||||
#define INTERP_565_MASK_1_3(v) (v & 0xF81F)
|
||||
#define INTERP_565_MASK_SHIFT_2_4(v) ((v & 0x7E0) >> 5)
|
||||
#define INTERP_565_MASK_SHIFTBACK_2_4(v) (INTERP_565_MASK_1_3(v) << 5)
|
||||
HQ4X_INTERP1(565, 16)
|
||||
HQ4X_INTERP2(565, 16)
|
||||
HQ4X_INTERP3(565, 16)
|
||||
HQ4X_INTERP5(565, 16)
|
||||
HQ4X_INTERP6(565, 16)
|
||||
HQ4X_INTERP7(565, 16)
|
||||
HQ4X_INTERP8(565, 16)
|
||||
#endif /* !_16BPP_HACK */
|
||||
|
||||
#define INTERP_8888_MASK_1_3(v) (v & 0x00FF00FF)
|
||||
#define INTERP_8888_MASK_SHIFT_2_4(v) ((v & 0xFF00FF00) >> 8)
|
||||
#define INTERP_8888_MASK_SHIFTBACK_2_4(v) (INTERP_8888_MASK_1_3(v) << 8)
|
||||
HQ4X_INTERP1(8888, 32)
|
||||
HQ4X_INTERP2(8888, 32)
|
||||
HQ4X_INTERP3(8888, 32)
|
||||
HQ4X_INTERP5(8888, 32)
|
||||
HQ4X_INTERP6(8888, 32)
|
||||
HQ4X_INTERP7(8888, 32)
|
||||
HQ4X_INTERP8(8888, 32)
|
||||
|
||||
#define PIXEL00_0 *((int*)(pOut)) = c[5];
|
||||
#define PIXEL00_11 hq4x_Interp1(pOut, c[5], c[4]);
|
||||
#define PIXEL00_12 hq4x_Interp1(pOut, c[5], c[2]);
|
||||
#define PIXEL00_20 hq4x_Interp2(pOut, c[5], c[2], c[4]);
|
||||
#define PIXEL00_50 hq4x_Interp5(pOut, c[2], c[4]);
|
||||
#define PIXEL00_80 hq4x_Interp8(pOut, c[5], c[1]);
|
||||
#define PIXEL00_81 hq4x_Interp8(pOut, c[5], c[4]);
|
||||
#define PIXEL00_82 hq4x_Interp8(pOut, c[5], c[2]);
|
||||
#define PIXEL01_0 *((int*)(pOut+BPP)) = c[5];
|
||||
#define PIXEL01_10 hq4x_Interp1(pOut+BPP, c[5], c[1]);
|
||||
#define PIXEL01_12 hq4x_Interp1(pOut+BPP, c[5], c[2]);
|
||||
#define PIXEL01_14 hq4x_Interp1(pOut+BPP, c[2], c[5]);
|
||||
#define PIXEL01_21 hq4x_Interp2(pOut+BPP, c[2], c[5], c[4]);
|
||||
#define PIXEL01_31 hq4x_Interp3(pOut+BPP, c[5], c[4]);
|
||||
#define PIXEL01_50 hq4x_Interp5(pOut+BPP, c[2], c[5]);
|
||||
#define PIXEL01_60 hq4x_Interp6(pOut+BPP, c[5], c[2], c[4]);
|
||||
#define PIXEL01_61 hq4x_Interp6(pOut+BPP, c[5], c[2], c[1]);
|
||||
#define PIXEL01_82 hq4x_Interp8(pOut+BPP, c[5], c[2]);
|
||||
#define PIXEL01_83 hq4x_Interp8(pOut+BPP, c[2], c[4]);
|
||||
#define PIXEL02_0 *((int*)(pOut+BPP2)) = c[5];
|
||||
#define PIXEL02_10 hq4x_Interp1(pOut+BPP2, c[5], c[3]);
|
||||
#define PIXEL02_11 hq4x_Interp1(pOut+BPP2, c[5], c[2]);
|
||||
#define PIXEL02_13 hq4x_Interp1(pOut+BPP2, c[2], c[5]);
|
||||
#define PIXEL02_21 hq4x_Interp2(pOut+BPP2, c[2], c[5], c[6]);
|
||||
#define PIXEL02_32 hq4x_Interp3(pOut+BPP2, c[5], c[6]);
|
||||
#define PIXEL02_50 hq4x_Interp5(pOut+BPP2, c[2], c[5]);
|
||||
#define PIXEL02_60 hq4x_Interp6(pOut+BPP2, c[5], c[2], c[6]);
|
||||
#define PIXEL02_61 hq4x_Interp6(pOut+BPP2, c[5], c[2], c[3]);
|
||||
#define PIXEL02_81 hq4x_Interp8(pOut+BPP2, c[5], c[2]);
|
||||
#define PIXEL02_83 hq4x_Interp8(pOut+BPP2, c[2], c[6]);
|
||||
#define PIXEL03_0 *((int*)(pOut+BPP3)) = c[5];
|
||||
#define PIXEL03_11 hq4x_Interp1(pOut+BPP3, c[5], c[2]);
|
||||
#define PIXEL03_12 hq4x_Interp1(pOut+BPP3, c[5], c[6]);
|
||||
#define PIXEL03_20 hq4x_Interp2(pOut+BPP3, c[5], c[2], c[6]);
|
||||
#define PIXEL03_50 hq4x_Interp5(pOut+BPP3, c[2], c[6]);
|
||||
#define PIXEL03_80 hq4x_Interp8(pOut+BPP3, c[5], c[3]);
|
||||
#define PIXEL03_81 hq4x_Interp8(pOut+BPP3, c[5], c[2]);
|
||||
#define PIXEL03_82 hq4x_Interp8(pOut+BPP3, c[5], c[6]);
|
||||
#define PIXEL10_0 *((int*)(pOut+BpL)) = c[5];
|
||||
#define PIXEL10_10 hq4x_Interp1(pOut+BpL, c[5], c[1]);
|
||||
#define PIXEL10_11 hq4x_Interp1(pOut+BpL, c[5], c[4]);
|
||||
#define PIXEL10_13 hq4x_Interp1(pOut+BpL, c[4], c[5]);
|
||||
#define PIXEL10_21 hq4x_Interp2(pOut+BpL, c[4], c[5], c[2]);
|
||||
#define PIXEL10_32 hq4x_Interp3(pOut+BpL, c[5], c[2]);
|
||||
#define PIXEL10_50 hq4x_Interp5(pOut+BpL, c[4], c[5]);
|
||||
#define PIXEL10_60 hq4x_Interp6(pOut+BpL, c[5], c[4], c[2]);
|
||||
#define PIXEL10_61 hq4x_Interp6(pOut+BpL, c[5], c[4], c[1]);
|
||||
#define PIXEL10_81 hq4x_Interp8(pOut+BpL, c[5], c[4]);
|
||||
#define PIXEL10_83 hq4x_Interp8(pOut+BpL, c[4], c[2]);
|
||||
#define PIXEL11_0 *((int*)(pOut+BpL+BPP)) = c[5];
|
||||
#define PIXEL11_30 hq4x_Interp3(pOut+BpL+BPP, c[5], c[1]);
|
||||
#define PIXEL11_31 hq4x_Interp3(pOut+BpL+BPP, c[5], c[4]);
|
||||
#define PIXEL11_32 hq4x_Interp3(pOut+BpL+BPP, c[5], c[2]);
|
||||
#define PIXEL11_70 hq4x_Interp7(pOut+BpL+BPP, c[5], c[4], c[2]);
|
||||
#define PIXEL12_0 *((int*)(pOut+BpL+BPP2)) = c[5];
|
||||
#define PIXEL12_30 hq4x_Interp3(pOut+BpL+BPP2, c[5], c[3]);
|
||||
#define PIXEL12_31 hq4x_Interp3(pOut+BpL+BPP2, c[5], c[2]);
|
||||
#define PIXEL12_32 hq4x_Interp3(pOut+BpL+BPP2, c[5], c[6]);
|
||||
#define PIXEL12_70 hq4x_Interp7(pOut+BpL+BPP2, c[5], c[6], c[2]);
|
||||
#define PIXEL13_0 *((int*)(pOut+BpL+BPP3)) = c[5];
|
||||
#define PIXEL13_10 hq4x_Interp1(pOut+BpL+BPP3, c[5], c[3]);
|
||||
#define PIXEL13_12 hq4x_Interp1(pOut+BpL+BPP3, c[5], c[6]);
|
||||
#define PIXEL13_14 hq4x_Interp1(pOut+BpL+BPP3, c[6], c[5]);
|
||||
#define PIXEL13_21 hq4x_Interp2(pOut+BpL+BPP3, c[6], c[5], c[2]);
|
||||
#define PIXEL13_31 hq4x_Interp3(pOut+BpL+BPP3, c[5], c[2]);
|
||||
#define PIXEL13_50 hq4x_Interp5(pOut+BpL+BPP3, c[6], c[5]);
|
||||
#define PIXEL13_60 hq4x_Interp6(pOut+BpL+BPP3, c[5], c[6], c[2]);
|
||||
#define PIXEL13_61 hq4x_Interp6(pOut+BpL+BPP3, c[5], c[6], c[3]);
|
||||
#define PIXEL13_82 hq4x_Interp8(pOut+BpL+BPP3, c[5], c[6]);
|
||||
#define PIXEL13_83 hq4x_Interp8(pOut+BpL+BPP3, c[6], c[2]);
|
||||
#define PIXEL20_0 *((int*)(pOut+BpL+BpL)) = c[5];
|
||||
#define PIXEL20_10 hq4x_Interp1(pOut+BpL+BpL, c[5], c[7]);
|
||||
#define PIXEL20_12 hq4x_Interp1(pOut+BpL+BpL, c[5], c[4]);
|
||||
#define PIXEL20_14 hq4x_Interp1(pOut+BpL+BpL, c[4], c[5]);
|
||||
#define PIXEL20_21 hq4x_Interp2(pOut+BpL+BpL, c[4], c[5], c[8]);
|
||||
#define PIXEL20_31 hq4x_Interp3(pOut+BpL+BpL, c[5], c[8]);
|
||||
#define PIXEL20_50 hq4x_Interp5(pOut+BpL+BpL, c[4], c[5]);
|
||||
#define PIXEL20_60 hq4x_Interp6(pOut+BpL+BpL, c[5], c[4], c[8]);
|
||||
#define PIXEL20_61 hq4x_Interp6(pOut+BpL+BpL, c[5], c[4], c[7]);
|
||||
#define PIXEL20_82 hq4x_Interp8(pOut+BpL+BpL, c[5], c[4]);
|
||||
#define PIXEL20_83 hq4x_Interp8(pOut+BpL+BpL, c[4], c[8]);
|
||||
#define PIXEL21_0 *((int*)(pOut+BpL+BpL+BPP)) = c[5];
|
||||
#define PIXEL21_30 hq4x_Interp3(pOut+BpL+BpL+BPP, c[5], c[7]);
|
||||
#define PIXEL21_31 hq4x_Interp3(pOut+BpL+BpL+BPP, c[5], c[8]);
|
||||
#define PIXEL21_32 hq4x_Interp3(pOut+BpL+BpL+BPP, c[5], c[4]);
|
||||
#define PIXEL21_70 hq4x_Interp7(pOut+BpL+BpL+BPP, c[5], c[4], c[8]);
|
||||
#define PIXEL22_0 *((int*)(pOut+BpL+BpL+BPP2)) = c[5];
|
||||
#define PIXEL22_30 hq4x_Interp3(pOut+BpL+BpL+BPP2, c[5], c[9]);
|
||||
#define PIXEL22_31 hq4x_Interp3(pOut+BpL+BpL+BPP2, c[5], c[6]);
|
||||
#define PIXEL22_32 hq4x_Interp3(pOut+BpL+BpL+BPP2, c[5], c[8]);
|
||||
#define PIXEL22_70 hq4x_Interp7(pOut+BpL+BpL+BPP2, c[5], c[6], c[8]);
|
||||
#define PIXEL23_0 *((int*)(pOut+BpL+BpL+BPP3)) = c[5];
|
||||
#define PIXEL23_10 hq4x_Interp1(pOut+BpL+BpL+BPP3, c[5], c[9]);
|
||||
#define PIXEL23_11 hq4x_Interp1(pOut+BpL+BpL+BPP3, c[5], c[6]);
|
||||
#define PIXEL23_13 hq4x_Interp1(pOut+BpL+BpL+BPP3, c[6], c[5]);
|
||||
#define PIXEL23_21 hq4x_Interp2(pOut+BpL+BpL+BPP3, c[6], c[5], c[8]);
|
||||
#define PIXEL23_32 hq4x_Interp3(pOut+BpL+BpL+BPP3, c[5], c[8]);
|
||||
#define PIXEL23_50 hq4x_Interp5(pOut+BpL+BpL+BPP3, c[6], c[5]);
|
||||
#define PIXEL23_60 hq4x_Interp6(pOut+BpL+BpL+BPP3, c[5], c[6], c[8]);
|
||||
#define PIXEL23_61 hq4x_Interp6(pOut+BpL+BpL+BPP3, c[5], c[6], c[9]);
|
||||
#define PIXEL23_81 hq4x_Interp8(pOut+BpL+BpL+BPP3, c[5], c[6]);
|
||||
#define PIXEL23_83 hq4x_Interp8(pOut+BpL+BpL+BPP3, c[6], c[8]);
|
||||
#define PIXEL30_0 *((int*)(pOut+BpL+BpL+BpL)) = c[5];
|
||||
#define PIXEL30_11 hq4x_Interp1(pOut+BpL+BpL+BpL, c[5], c[8]);
|
||||
#define PIXEL30_12 hq4x_Interp1(pOut+BpL+BpL+BpL, c[5], c[4]);
|
||||
#define PIXEL30_20 hq4x_Interp2(pOut+BpL+BpL+BpL, c[5], c[8], c[4]);
|
||||
#define PIXEL30_50 hq4x_Interp5(pOut+BpL+BpL+BpL, c[8], c[4]);
|
||||
#define PIXEL30_80 hq4x_Interp8(pOut+BpL+BpL+BpL, c[5], c[7]);
|
||||
#define PIXEL30_81 hq4x_Interp8(pOut+BpL+BpL+BpL, c[5], c[8]);
|
||||
#define PIXEL30_82 hq4x_Interp8(pOut+BpL+BpL+BpL, c[5], c[4]);
|
||||
#define PIXEL31_0 *((int*)(pOut+BpL+BpL+BpL+BPP)) = c[5];
|
||||
#define PIXEL31_10 hq4x_Interp1(pOut+BpL+BpL+BpL+BPP, c[5], c[7]);
|
||||
#define PIXEL31_11 hq4x_Interp1(pOut+BpL+BpL+BpL+BPP, c[5], c[8]);
|
||||
#define PIXEL31_13 hq4x_Interp1(pOut+BpL+BpL+BpL+BPP, c[8], c[5]);
|
||||
#define PIXEL31_21 hq4x_Interp2(pOut+BpL+BpL+BpL+BPP, c[8], c[5], c[4]);
|
||||
#define PIXEL31_32 hq4x_Interp3(pOut+BpL+BpL+BpL+BPP, c[5], c[4]);
|
||||
#define PIXEL31_50 hq4x_Interp5(pOut+BpL+BpL+BpL+BPP, c[8], c[5]);
|
||||
#define PIXEL31_60 hq4x_Interp6(pOut+BpL+BpL+BpL+BPP, c[5], c[8], c[4]);
|
||||
#define PIXEL31_61 hq4x_Interp6(pOut+BpL+BpL+BpL+BPP, c[5], c[8], c[7]);
|
||||
#define PIXEL31_81 hq4x_Interp8(pOut+BpL+BpL+BpL+BPP, c[5], c[8]);
|
||||
#define PIXEL31_83 hq4x_Interp8(pOut+BpL+BpL+BpL+BPP, c[8], c[4]);
|
||||
#define PIXEL32_0 *((int*)(pOut+BpL+BpL+BpL+BPP2)) = c[5];
|
||||
#define PIXEL32_10 hq4x_Interp1(pOut+BpL+BpL+BpL+BPP2, c[5], c[9]);
|
||||
#define PIXEL32_12 hq4x_Interp1(pOut+BpL+BpL+BpL+BPP2, c[5], c[8]);
|
||||
#define PIXEL32_14 hq4x_Interp1(pOut+BpL+BpL+BpL+BPP2, c[8], c[5]);
|
||||
#define PIXEL32_21 hq4x_Interp2(pOut+BpL+BpL+BpL+BPP2, c[8], c[5], c[6]);
|
||||
#define PIXEL32_31 hq4x_Interp3(pOut+BpL+BpL+BpL+BPP2, c[5], c[6]);
|
||||
#define PIXEL32_50 hq4x_Interp5(pOut+BpL+BpL+BpL+BPP2, c[8], c[5]);
|
||||
#define PIXEL32_60 hq4x_Interp6(pOut+BpL+BpL+BpL+BPP2, c[5], c[8], c[6]);
|
||||
#define PIXEL32_61 hq4x_Interp6(pOut+BpL+BpL+BpL+BPP2, c[5], c[8], c[9]);
|
||||
#define PIXEL32_82 hq4x_Interp8(pOut+BpL+BpL+BpL+BPP2, c[5], c[8]);
|
||||
#define PIXEL32_83 hq4x_Interp8(pOut+BpL+BpL+BpL+BPP2, c[8], c[6]);
|
||||
#define PIXEL33_0 *((int*)(pOut+BpL+BpL+BpL+BPP3)) = c[5];
|
||||
#define PIXEL33_11 hq4x_Interp1(pOut+BpL+BpL+BpL+BPP3, c[5], c[6]);
|
||||
#define PIXEL33_12 hq4x_Interp1(pOut+BpL+BpL+BpL+BPP3, c[5], c[8]);
|
||||
#define PIXEL33_20 hq4x_Interp2(pOut+BpL+BpL+BpL+BPP3, c[5], c[8], c[6]);
|
||||
#define PIXEL33_50 hq4x_Interp5(pOut+BpL+BpL+BpL+BPP3, c[8], c[6]);
|
||||
#define PIXEL33_80 hq4x_Interp8(pOut+BpL+BpL+BpL+BPP3, c[5], c[9]);
|
||||
#define PIXEL33_81 hq4x_Interp8(pOut+BpL+BpL+BpL+BPP3, c[5], c[6]);
|
||||
#define PIXEL33_82 hq4x_Interp8(pOut+BpL+BpL+BpL+BPP3, c[5], c[8]);
|
||||
|
||||
#define HQ4X_DIFF(n, b) \
|
||||
static int Diff_##n (uint##b w1, uint##b w2) \
|
||||
{ \
|
||||
int YUV1, YUV2; \
|
||||
YUV1 = RGB##n##toYUV(w1); \
|
||||
YUV2 = RGB##n##toYUV(w2); \
|
||||
return ( ( abs((YUV1 & Ymask) - (YUV2 & Ymask)) > trY ) || \
|
||||
( abs((YUV1 & Umask) - (YUV2 & Umask)) > trU ) || \
|
||||
( abs((YUV1 & Vmask) - (YUV2 & Vmask)) > trV ) ); \
|
||||
}
|
||||
|
||||
HQ4X_DIFF(888, 32)
|
||||
|
||||
#if !_16BPP_HACK
|
||||
HQ4X_DIFF(444, 16)
|
||||
HQ4X_DIFF(555, 16)
|
||||
HQ4X_DIFF(565, 16)
|
||||
|
||||
void hq4x_4444(unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int SrcPPL, int BpL)
|
||||
{
|
||||
#define hq4x_Interp1 hq4x_Interp1_4444
|
||||
#define hq4x_Interp2 hq4x_Interp2_4444
|
||||
#define hq4x_Interp3 hq4x_Interp3_4444
|
||||
#define hq4x_Interp4 hq4x_Interp4_4444
|
||||
#define hq4x_Interp5 hq4x_Interp5_4444
|
||||
#define hq4x_Interp6 hq4x_Interp6_4444
|
||||
#define hq4x_Interp7 hq4x_Interp7_4444
|
||||
#define hq4x_Interp8 hq4x_Interp8_4444
|
||||
#define Diff Diff_444
|
||||
#define BPP 2
|
||||
#define BPP2 4
|
||||
#define BPP3 6
|
||||
|
||||
int i, j, k;
|
||||
int prevline, nextline;
|
||||
uint16 w[10];
|
||||
uint16 c[10];
|
||||
|
||||
int pattern;
|
||||
int flag;
|
||||
|
||||
int YUV1, YUV2;
|
||||
|
||||
// +----+----+----+
|
||||
// | | | |
|
||||
// | w1 | w2 | w3 |
|
||||
// +----+----+----+
|
||||
// | | | |
|
||||
// | w4 | w5 | w6 |
|
||||
// +----+----+----+
|
||||
// | | | |
|
||||
// | w7 | w8 | w9 |
|
||||
// +----+----+----+
|
||||
|
||||
for (j = 0; j < Yres; j++) {
|
||||
if (j>0) prevline = -SrcPPL*2; else prevline = 0;
|
||||
if (j<Yres-1) nextline = SrcPPL*2; else nextline = 0;
|
||||
|
||||
for (i=0; i<Xres; i++) {
|
||||
w[2] = *((uint16*)(pIn + prevline));
|
||||
w[5] = *((uint16*)pIn);
|
||||
w[8] = *((uint16*)(pIn + nextline));
|
||||
|
||||
if (i>0) {
|
||||
w[1] = *((uint16*)(pIn + prevline - 2));
|
||||
w[4] = *((uint16*)(pIn - 2));
|
||||
w[7] = *((uint16*)(pIn + nextline - 2));
|
||||
} else {
|
||||
w[1] = w[2];
|
||||
w[4] = w[5];
|
||||
w[7] = w[8];
|
||||
}
|
||||
|
||||
if (i<Xres-1) {
|
||||
w[3] = *((uint16*)(pIn + prevline + 2));
|
||||
w[6] = *((uint16*)(pIn + 2));
|
||||
w[9] = *((uint16*)(pIn + nextline + 2));
|
||||
} else {
|
||||
w[3] = w[2];
|
||||
w[6] = w[5];
|
||||
w[9] = w[8];
|
||||
}
|
||||
|
||||
pattern = 0;
|
||||
flag = 1;
|
||||
|
||||
YUV1 = RGB444toYUV(w[5]);
|
||||
|
||||
for (k=1; k<=9; k++) {
|
||||
if (k==5) continue;
|
||||
|
||||
if ( w[k] != w[5] ) {
|
||||
YUV2 = RGB444toYUV(w[k]);
|
||||
if ( ( abs((YUV1 & Ymask) - (YUV2 & Ymask)) > trY ) ||
|
||||
( abs((YUV1 & Umask) - (YUV2 & Umask)) > trU ) ||
|
||||
( abs((YUV1 & Vmask) - (YUV2 & Vmask)) > trV ) )
|
||||
pattern |= flag;
|
||||
}
|
||||
flag <<= 1;
|
||||
}
|
||||
|
||||
for (k=1; k<=9; k++)
|
||||
c[k] = w[k];
|
||||
|
||||
#include "TextureFilters_hq4x.h"
|
||||
|
||||
pIn+=2;
|
||||
pOut+=8;
|
||||
}
|
||||
pIn += 2*(SrcPPL-Xres);
|
||||
pOut+= 8*(SrcPPL-Xres);
|
||||
pOut+=BpL;
|
||||
pOut+=BpL;
|
||||
pOut+=BpL;
|
||||
}
|
||||
|
||||
#undef BPP
|
||||
#undef BPP2
|
||||
#undef BPP3
|
||||
#undef Diff
|
||||
#undef hq4x_Interp1
|
||||
#undef hq4x_Interp2
|
||||
#undef hq4x_Interp3
|
||||
#undef hq4x_Interp4
|
||||
#undef hq4x_Interp5
|
||||
#undef hq4x_Interp6
|
||||
#undef hq4x_Interp7
|
||||
#undef hq4x_Interp8
|
||||
}
|
||||
|
||||
void hq4x_1555(unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int SrcPPL, int BpL)
|
||||
{
|
||||
#define hq4x_Interp1 hq4x_Interp1_1555
|
||||
#define hq4x_Interp2 hq4x_Interp2_1555
|
||||
#define hq4x_Interp3 hq4x_Interp3_1555
|
||||
#define hq4x_Interp4 hq4x_Interp4_1555
|
||||
#define hq4x_Interp5 hq4x_Interp5_1555
|
||||
#define hq4x_Interp6 hq4x_Interp6_1555
|
||||
#define hq4x_Interp7 hq4x_Interp7_1555
|
||||
#define hq4x_Interp8 hq4x_Interp8_1555
|
||||
#define Diff Diff_555
|
||||
#define BPP 2
|
||||
#define BPP2 4
|
||||
#define BPP3 6
|
||||
|
||||
int i, j, k;
|
||||
int prevline, nextline;
|
||||
uint16 w[10];
|
||||
uint16 c[10];
|
||||
|
||||
int pattern;
|
||||
int flag;
|
||||
|
||||
int YUV1, YUV2;
|
||||
|
||||
// +----+----+----+
|
||||
// | | | |
|
||||
// | w1 | w2 | w3 |
|
||||
// +----+----+----+
|
||||
// | | | |
|
||||
// | w4 | w5 | w6 |
|
||||
// +----+----+----+
|
||||
// | | | |
|
||||
// | w7 | w8 | w9 |
|
||||
// +----+----+----+
|
||||
|
||||
for (j = 0; j < Yres; j++) {
|
||||
if (j>0) prevline = -SrcPPL*2; else prevline = 0;
|
||||
if (j<Yres-1) nextline = SrcPPL*2; else nextline = 0;
|
||||
|
||||
for (i=0; i<Xres; i++) {
|
||||
w[2] = *((uint16*)(pIn + prevline));
|
||||
w[5] = *((uint16*)pIn);
|
||||
w[8] = *((uint16*)(pIn + nextline));
|
||||
|
||||
if (i>0) {
|
||||
w[1] = *((uint16*)(pIn + prevline - 2));
|
||||
w[4] = *((uint16*)(pIn - 2));
|
||||
w[7] = *((uint16*)(pIn + nextline - 2));
|
||||
} else {
|
||||
w[1] = w[2];
|
||||
w[4] = w[5];
|
||||
w[7] = w[8];
|
||||
}
|
||||
|
||||
if (i<Xres-1) {
|
||||
w[3] = *((uint16*)(pIn + prevline + 2));
|
||||
w[6] = *((uint16*)(pIn + 2));
|
||||
w[9] = *((uint16*)(pIn + nextline + 2));
|
||||
} else {
|
||||
w[3] = w[2];
|
||||
w[6] = w[5];
|
||||
w[9] = w[8];
|
||||
}
|
||||
|
||||
pattern = 0;
|
||||
flag = 1;
|
||||
|
||||
YUV1 = RGB555toYUV(w[5]);
|
||||
|
||||
for (k=1; k<=9; k++) {
|
||||
if (k==5) continue;
|
||||
|
||||
if ( w[k] != w[5] ) {
|
||||
YUV2 = RGB555toYUV(w[k]);
|
||||
if ( ( abs((YUV1 & Ymask) - (YUV2 & Ymask)) > trY ) ||
|
||||
( abs((YUV1 & Umask) - (YUV2 & Umask)) > trU ) ||
|
||||
( abs((YUV1 & Vmask) - (YUV2 & Vmask)) > trV ) )
|
||||
pattern |= flag;
|
||||
}
|
||||
flag <<= 1;
|
||||
}
|
||||
|
||||
for (k=1; k<=9; k++)
|
||||
c[k] = w[k];
|
||||
|
||||
#include "TextureFilters_hq4x.h"
|
||||
|
||||
pIn+=2;
|
||||
pOut+=8;
|
||||
}
|
||||
pIn += 2*(SrcPPL-Xres);
|
||||
pOut+= 8*(SrcPPL-Xres);
|
||||
pOut+=BpL;
|
||||
pOut+=BpL;
|
||||
pOut+=BpL;
|
||||
}
|
||||
|
||||
#undef BPP
|
||||
#undef BPP2
|
||||
#undef BPP3
|
||||
#undef Diff
|
||||
#undef hq4x_Interp1
|
||||
#undef hq4x_Interp2
|
||||
#undef hq4x_Interp3
|
||||
#undef hq4x_Interp4
|
||||
#undef hq4x_Interp5
|
||||
#undef hq4x_Interp6
|
||||
#undef hq4x_Interp7
|
||||
#undef hq4x_Interp8
|
||||
}
|
||||
|
||||
void hq4x_565(unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int SrcPPL, int BpL)
|
||||
{
|
||||
#define hq4x_Interp1 hq4x_Interp1_565
|
||||
#define hq4x_Interp2 hq4x_Interp2_565
|
||||
#define hq4x_Interp3 hq4x_Interp3_565
|
||||
#define hq4x_Interp4 hq4x_Interp4_565
|
||||
#define hq4x_Interp5 hq4x_Interp5_565
|
||||
#define hq4x_Interp6 hq4x_Interp6_565
|
||||
#define hq4x_Interp7 hq4x_Interp7_565
|
||||
#define hq4x_Interp8 hq4x_Interp8_565
|
||||
#define Diff Diff_565
|
||||
#define BPP 2
|
||||
#define BPP2 4
|
||||
#define BPP3 6
|
||||
|
||||
int i, j, k;
|
||||
int prevline, nextline;
|
||||
uint16 w[10];
|
||||
uint16 c[10];
|
||||
|
||||
int pattern;
|
||||
int flag;
|
||||
|
||||
int YUV1, YUV2;
|
||||
|
||||
// +----+----+----+
|
||||
// | | | |
|
||||
// | w1 | w2 | w3 |
|
||||
// +----+----+----+
|
||||
// | | | |
|
||||
// | w4 | w5 | w6 |
|
||||
// +----+----+----+
|
||||
// | | | |
|
||||
// | w7 | w8 | w9 |
|
||||
// +----+----+----+
|
||||
|
||||
for (j = 0; j < Yres; j++) {
|
||||
if (j>0) prevline = -SrcPPL*2; else prevline = 0;
|
||||
if (j<Yres-1) nextline = SrcPPL*2; else nextline = 0;
|
||||
|
||||
for (i=0; i<Xres; i++) {
|
||||
w[2] = *((uint16*)(pIn + prevline));
|
||||
w[5] = *((uint16*)pIn);
|
||||
w[8] = *((uint16*)(pIn + nextline));
|
||||
|
||||
if (i>0) {
|
||||
w[1] = *((uint16*)(pIn + prevline - 2));
|
||||
w[4] = *((uint16*)(pIn - 2));
|
||||
w[7] = *((uint16*)(pIn + nextline - 2));
|
||||
} else {
|
||||
w[1] = w[2];
|
||||
w[4] = w[5];
|
||||
w[7] = w[8];
|
||||
}
|
||||
|
||||
if (i<Xres-1) {
|
||||
w[3] = *((uint16*)(pIn + prevline + 2));
|
||||
w[6] = *((uint16*)(pIn + 2));
|
||||
w[9] = *((uint16*)(pIn + nextline + 2));
|
||||
} else {
|
||||
w[3] = w[2];
|
||||
w[6] = w[5];
|
||||
w[9] = w[8];
|
||||
}
|
||||
|
||||
pattern = 0;
|
||||
flag = 1;
|
||||
|
||||
YUV1 = RGB565toYUV(w[5]);
|
||||
|
||||
for (k=1; k<=9; k++) {
|
||||
if (k==5) continue;
|
||||
|
||||
if ( w[k] != w[5] ) {
|
||||
YUV2 = RGB565toYUV(w[k]);
|
||||
if ( ( abs((YUV1 & Ymask) - (YUV2 & Ymask)) > trY ) ||
|
||||
( abs((YUV1 & Umask) - (YUV2 & Umask)) > trU ) ||
|
||||
( abs((YUV1 & Vmask) - (YUV2 & Vmask)) > trV ) )
|
||||
pattern |= flag;
|
||||
}
|
||||
flag <<= 1;
|
||||
}
|
||||
|
||||
for (k=1; k<=9; k++)
|
||||
c[k] = w[k];
|
||||
|
||||
#include "TextureFilters_hq4x.h"
|
||||
|
||||
pIn+=2;
|
||||
pOut+=8;
|
||||
}
|
||||
pIn += 2*(SrcPPL-Xres);
|
||||
pOut+= 8*(SrcPPL-Xres);
|
||||
pOut+=BpL;
|
||||
pOut+=BpL;
|
||||
pOut+=BpL;
|
||||
}
|
||||
|
||||
#undef BPP
|
||||
#undef BPP2
|
||||
#undef BPP3
|
||||
#undef Diff
|
||||
#undef hq4x_Interp1
|
||||
#undef hq4x_Interp2
|
||||
#undef hq4x_Interp3
|
||||
#undef hq4x_Interp4
|
||||
#undef hq4x_Interp5
|
||||
#undef hq4x_Interp6
|
||||
#undef hq4x_Interp7
|
||||
#undef hq4x_Interp8
|
||||
}
|
||||
#endif /* !_16BPP_HACK */
|
||||
|
||||
void hq4x_8888(unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int SrcPPL, int BpL)
|
||||
{
|
||||
#define hq4x_Interp1 hq4x_Interp1_8888
|
||||
#define hq4x_Interp2 hq4x_Interp2_8888
|
||||
#define hq4x_Interp3 hq4x_Interp3_8888
|
||||
#define hq4x_Interp4 hq4x_Interp4_8888
|
||||
#define hq4x_Interp5 hq4x_Interp5_8888
|
||||
#define hq4x_Interp6 hq4x_Interp6_8888
|
||||
#define hq4x_Interp7 hq4x_Interp7_8888
|
||||
#define hq4x_Interp8 hq4x_Interp8_8888
|
||||
#define Diff Diff_888
|
||||
#define BPP 4
|
||||
#define BPP2 8
|
||||
#define BPP3 12
|
||||
|
||||
int i, j, k;
|
||||
int prevline, nextline;
|
||||
uint32 w[10];
|
||||
uint32 c[10];
|
||||
|
||||
int pattern;
|
||||
int flag;
|
||||
|
||||
int YUV1, YUV2;
|
||||
|
||||
// +----+----+----+
|
||||
// | | | |
|
||||
// | w1 | w2 | w3 |
|
||||
// +----+----+----+
|
||||
// | | | |
|
||||
// | w4 | w5 | w6 |
|
||||
// +----+----+----+
|
||||
// | | | |
|
||||
// | w7 | w8 | w9 |
|
||||
// +----+----+----+
|
||||
|
||||
for (j = 0; j < Yres; j++) {
|
||||
if (j>0) prevline = -SrcPPL*4; else prevline = 0;
|
||||
if (j<Yres-1) nextline = SrcPPL*4; else nextline = 0;
|
||||
|
||||
for (i=0; i<Xres; i++) {
|
||||
w[2] = *((uint32*)(pIn + prevline));
|
||||
w[5] = *((uint32*)pIn);
|
||||
w[8] = *((uint32*)(pIn + nextline));
|
||||
|
||||
if (i>0) {
|
||||
w[1] = *((uint32*)(pIn + prevline - 4));
|
||||
w[4] = *((uint32*)(pIn - 4));
|
||||
w[7] = *((uint32*)(pIn + nextline - 4));
|
||||
} else {
|
||||
w[1] = w[2];
|
||||
w[4] = w[5];
|
||||
w[7] = w[8];
|
||||
}
|
||||
|
||||
if (i<Xres-1) {
|
||||
w[3] = *((uint32*)(pIn + prevline + 4));
|
||||
w[6] = *((uint32*)(pIn + 4));
|
||||
w[9] = *((uint32*)(pIn + nextline + 4));
|
||||
} else {
|
||||
w[3] = w[2];
|
||||
w[6] = w[5];
|
||||
w[9] = w[8];
|
||||
}
|
||||
|
||||
pattern = 0;
|
||||
flag = 1;
|
||||
|
||||
YUV1 = RGB888toYUV(w[5]);
|
||||
|
||||
for (k=1; k<=9; k++) {
|
||||
if (k==5) continue;
|
||||
|
||||
if ( w[k] != w[5] ) {
|
||||
YUV2 = RGB888toYUV(w[k]);
|
||||
if ( ( abs((YUV1 & Ymask) - (YUV2 & Ymask)) > trY ) ||
|
||||
( abs((YUV1 & Umask) - (YUV2 & Umask)) > trU ) ||
|
||||
( abs((YUV1 & Vmask) - (YUV2 & Vmask)) > trV ) )
|
||||
pattern |= flag;
|
||||
}
|
||||
flag <<= 1;
|
||||
}
|
||||
|
||||
for (k=1; k<=9; k++)
|
||||
c[k] = w[k];
|
||||
|
||||
#include "TextureFilters_hq4x.h"
|
||||
|
||||
pIn+=4;
|
||||
pOut+=16;
|
||||
}
|
||||
|
||||
pIn += 4*(SrcPPL-Xres);
|
||||
pOut+= 16*(SrcPPL-Xres);
|
||||
pOut+=BpL;
|
||||
pOut+=BpL;
|
||||
pOut+=BpL;
|
||||
}
|
||||
|
||||
#undef BPP
|
||||
#undef BPP2
|
||||
#undef BPP3
|
||||
#undef Diff
|
||||
#undef hq4x_Interp1
|
||||
#undef hq4x_Interp2
|
||||
#undef hq4x_Interp3
|
||||
#undef hq4x_Interp4
|
||||
#undef hq4x_Interp5
|
||||
#undef hq4x_Interp6
|
||||
#undef hq4x_Interp7
|
||||
#undef hq4x_Interp8
|
||||
}
|
||||
|
||||
#if !_16BPP_HACK
|
||||
void hq4x_init(void)
|
||||
{
|
||||
static int done = 0;
|
||||
int r, g, b, Y, u, v, i, j, k;
|
||||
|
||||
if (done ) return;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
for (j = 0; j < 16; j++) {
|
||||
for (k = 0; k < 16; k++) {
|
||||
r = (i << 4) | i;
|
||||
g = (j << 4) | j;
|
||||
b = (k << 4) | k;
|
||||
|
||||
/* Microsoft's RGB888->YUV conversion */
|
||||
/*Y = ((( 66 * r + 129 * g + 25 * b + 128) >> 8) + 16) & 0xFF;
|
||||
u = ((( -38 * r - 74 * g + 112 * b + 128) >> 8) + 128) & 0xFF;
|
||||
v = ((( 112 * r - 94 * g - 18 * b + 128) >> 8) + 128) & 0xFF;*/
|
||||
|
||||
Y = (r + g + b) >> 2;
|
||||
u = 128 + ((r - b) >> 2);
|
||||
v = 128 + ((-r + 2*g -b)>>3);
|
||||
|
||||
RGB444toYUV[(i << 8) | (j << 4) | k] = (Y << 16) | (u << 8) | v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done = 1;
|
||||
}
|
||||
#endif /* !_16BPP_HACK */
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,433 @@
|
|||
/*
|
||||
* Texture Filtering
|
||||
* Version: 1.0
|
||||
*
|
||||
* Copyright (C) 2007 Hiroshi Morii All Rights Reserved.
|
||||
* Email koolsmoky(at)users.sourceforge.net
|
||||
* Web http://www.3dfxzone.it/koolsmoky
|
||||
*
|
||||
* this 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* this 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#pragma warning(disable: 4786)
|
||||
#endif
|
||||
|
||||
#include "TxCache.h"
|
||||
#include "TxDbg.h"
|
||||
#include <zlib/zlib.h>
|
||||
#include <Common/path.h>
|
||||
|
||||
TxCache::~TxCache()
|
||||
{
|
||||
/* free memory, clean up, etc */
|
||||
clear();
|
||||
|
||||
delete _txUtil;
|
||||
}
|
||||
|
||||
TxCache::TxCache(int options, int cachesize, const wchar_t *path, const wchar_t *ident,
|
||||
dispInfoFuncExt callback)
|
||||
{
|
||||
_txUtil = new TxUtil();
|
||||
|
||||
_options = options;
|
||||
_cacheSize = cachesize;
|
||||
_callback = callback;
|
||||
_totalSize = 0;
|
||||
|
||||
/* save path name */
|
||||
if (path)
|
||||
_path.assign(path);
|
||||
|
||||
/* save ROM name */
|
||||
if (ident)
|
||||
_ident.assign(ident);
|
||||
|
||||
/* zlib memory buffers to (de)compress hires textures */
|
||||
if (_options & (GZ_TEXCACHE|GZ_HIRESTEXCACHE)) {
|
||||
_gzdest0 = TxMemBuf::getInstance()->get(0);
|
||||
_gzdest1 = TxMemBuf::getInstance()->get(1);
|
||||
_gzdestLen = (TxMemBuf::getInstance()->size_of(0) < TxMemBuf::getInstance()->size_of(1)) ?
|
||||
TxMemBuf::getInstance()->size_of(0) : TxMemBuf::getInstance()->size_of(1);
|
||||
|
||||
if (!_gzdest0 || !_gzdest1 || !_gzdestLen) {
|
||||
_options &= ~(GZ_TEXCACHE|GZ_HIRESTEXCACHE);
|
||||
_gzdest0 = NULL;
|
||||
_gzdest1 = NULL;
|
||||
_gzdestLen = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean
|
||||
TxCache::add(uint64 checksum, GHQTexInfo *info, int dataSize)
|
||||
{
|
||||
/* NOTE: dataSize must be provided if info->data is zlib compressed. */
|
||||
|
||||
if (!checksum || !info->data) return 0;
|
||||
|
||||
uint8 *dest = info->data;
|
||||
uint16 format = info->format;
|
||||
|
||||
if (!dataSize) {
|
||||
dataSize = _txUtil->sizeofTx(info->width, info->height, info->format);
|
||||
|
||||
if (!dataSize) return 0;
|
||||
|
||||
if (_options & (GZ_TEXCACHE|GZ_HIRESTEXCACHE)) {
|
||||
/* zlib compress it. compression level:1 (best speed) */
|
||||
uint32 destLen = _gzdestLen;
|
||||
dest = (dest == _gzdest0) ? _gzdest1 : _gzdest0;
|
||||
if (compress2(dest, &destLen, info->data, dataSize, 1) != Z_OK) {
|
||||
dest = info->data;
|
||||
DBG_INFO(80, L"Error: zlib compression failed!\n");
|
||||
} else {
|
||||
DBG_INFO(80, L"zlib compressed: %.02fkb->%.02fkb\n", (float)dataSize/1000, (float)destLen/1000);
|
||||
dataSize = destLen;
|
||||
format |= GR_TEXFMT_GZ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if cache size exceeds limit, remove old cache */
|
||||
if (_cacheSize > 0) {
|
||||
_totalSize += dataSize;
|
||||
if ((_totalSize > _cacheSize) && !_cachelist.empty()) {
|
||||
/* _cachelist is arranged so that frequently used textures are in the back */
|
||||
std::list<uint64>::iterator itList = _cachelist.begin();
|
||||
while (itList != _cachelist.end()) {
|
||||
/* find it in _cache */
|
||||
std::map<uint64, TXCACHE*>::iterator itMap = _cache.find(*itList);
|
||||
if (itMap != _cache.end()) {
|
||||
/* yep we have it. remove it. */
|
||||
_totalSize -= (*itMap).second->size;
|
||||
free((*itMap).second->info.data);
|
||||
delete (*itMap).second;
|
||||
_cache.erase(itMap);
|
||||
}
|
||||
itList++;
|
||||
|
||||
/* check if memory cache has enough space */
|
||||
if (_totalSize <= _cacheSize)
|
||||
break;
|
||||
}
|
||||
/* remove from _cachelist */
|
||||
_cachelist.erase(_cachelist.begin(), itList);
|
||||
|
||||
DBG_INFO(80, L"+++++++++\n");
|
||||
}
|
||||
_totalSize -= dataSize;
|
||||
}
|
||||
|
||||
/* cache it */
|
||||
uint8 *tmpdata = (uint8*)malloc(dataSize);
|
||||
if (tmpdata) {
|
||||
TXCACHE *txCache = new TXCACHE;
|
||||
if (txCache) {
|
||||
/* we can directly write as we filter, but for now we get away
|
||||
* with doing memcpy after all the filtering is done.
|
||||
*/
|
||||
memcpy(tmpdata, dest, dataSize);
|
||||
|
||||
/* copy it */
|
||||
memcpy(&txCache->info, info, sizeof(GHQTexInfo));
|
||||
txCache->info.data = tmpdata;
|
||||
txCache->info.format = format;
|
||||
txCache->size = dataSize;
|
||||
|
||||
/* add to cache */
|
||||
if (_cacheSize > 0) {
|
||||
_cachelist.push_back(checksum);
|
||||
txCache->it = --(_cachelist.end());
|
||||
}
|
||||
/* _cache[checksum] = txCache; */
|
||||
_cache.insert(std::map<uint64, TXCACHE*>::value_type(checksum, txCache));
|
||||
|
||||
#ifdef DEBUG
|
||||
DBG_INFO(80, L"[%5d] added!! crc:%08X %08X %d x %d gfmt:%x total:%.02fmb\n",
|
||||
_cache.size(), (uint32)(checksum >> 32), (uint32)(checksum & 0xffffffff),
|
||||
info->width, info->height, info->format, (float)_totalSize/1000000);
|
||||
|
||||
DBG_INFO(80, L"smalllodlog2:%d largelodlog2:%d aspectratiolog2:%d\n",
|
||||
txCache->info.smallLodLog2, txCache->info.largeLodLog2, txCache->info.aspectRatioLog2);
|
||||
|
||||
if (info->tiles) {
|
||||
DBG_INFO(80, L"tiles:%d un-tiled size:%d x %d\n", info->tiles, info->untiled_width, info->untiled_height);
|
||||
}
|
||||
|
||||
if (_cacheSize > 0) {
|
||||
DBG_INFO(80, L"cache max config:%.02fmb\n", (float)_cacheSize/1000000);
|
||||
|
||||
if (_cache.size() != _cachelist.size()) {
|
||||
DBG_INFO(80, L"Error: cache/cachelist mismatch! (%d/%d)\n", _cache.size(), _cachelist.size());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* total cache size */
|
||||
_totalSize += dataSize;
|
||||
|
||||
return 1;
|
||||
}
|
||||
free(tmpdata);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
boolean
|
||||
TxCache::get(uint64 checksum, GHQTexInfo *info)
|
||||
{
|
||||
if (!checksum || _cache.empty()) return 0;
|
||||
|
||||
/* find a match in cache */
|
||||
std::map<uint64, TXCACHE*>::iterator itMap = _cache.find(checksum);
|
||||
if (itMap != _cache.end()) {
|
||||
/* yep, we've got it. */
|
||||
memcpy(info, &(((*itMap).second)->info), sizeof(GHQTexInfo));
|
||||
|
||||
/* push it to the back of the list */
|
||||
if (_cacheSize > 0) {
|
||||
_cachelist.erase(((*itMap).second)->it);
|
||||
_cachelist.push_back(checksum);
|
||||
((*itMap).second)->it = --(_cachelist.end());
|
||||
}
|
||||
|
||||
/* zlib decompress it */
|
||||
if (info->format & GR_TEXFMT_GZ) {
|
||||
uint32 destLen = _gzdestLen;
|
||||
uint8 *dest = (_gzdest0 == info->data) ? _gzdest1 : _gzdest0;
|
||||
if (uncompress(dest, &destLen, info->data, ((*itMap).second)->size) != Z_OK) {
|
||||
DBG_INFO(80, L"Error: zlib decompression failed!\n");
|
||||
return 0;
|
||||
}
|
||||
info->data = dest;
|
||||
info->format &= ~GR_TEXFMT_GZ;
|
||||
DBG_INFO(80, L"zlib decompressed: %.02fkb->%.02fkb\n", (float)(((*itMap).second)->size)/1000, (float)destLen/1000);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
boolean
|
||||
TxCache::save(const wchar_t *path, const wchar_t *filename, int config)
|
||||
{
|
||||
if (!_cache.empty()) {
|
||||
/* dump cache to disk */
|
||||
char cbuf[MAX_PATH];
|
||||
|
||||
CPath cachepath(stdstr().FromUTF16(path),"");
|
||||
cachepath.CreateDirectory();
|
||||
|
||||
/* Ugly hack to enable fopen/gzopen in Win9x */
|
||||
#ifdef WIN32
|
||||
wchar_t curpath[MAX_PATH];
|
||||
GETCWD(MAX_PATH, curpath);
|
||||
cachepath.ChangeDirectory();
|
||||
#else
|
||||
char curpath[MAX_PATH];
|
||||
wcstombs(cbuf, cachepath.string().c_str(), MAX_PATH);
|
||||
GETCWD(MAX_PATH, curpath);
|
||||
CHDIR(cbuf);
|
||||
#endif
|
||||
|
||||
#ifdef tofix
|
||||
wcstombs(cbuf, filename, MAX_PATH);
|
||||
|
||||
gzFile gzfp = gzopen(cbuf, "wb1");
|
||||
DBG_INFO(80, L"gzfp:%x file:%ls\n", gzfp, filename);
|
||||
if (gzfp) {
|
||||
/* write header to determine config match */
|
||||
gzwrite(gzfp, &config, 4);
|
||||
|
||||
std::map<uint64, TXCACHE*>::iterator itMap = _cache.begin();
|
||||
while (itMap != _cache.end()) {
|
||||
uint8 *dest = (*itMap).second->info.data;
|
||||
uint32 destLen = (*itMap).second->size;
|
||||
uint16 format = (*itMap).second->info.format;
|
||||
|
||||
/* to keep things simple, we save the texture data in a zlib uncompressed state. */
|
||||
/* sigh... for those who cannot wait the extra few seconds. changed to keep
|
||||
* texture data in a zlib compressed state. if the GZ_TEXCACHE or GZ_HIRESTEXCACHE
|
||||
* option is toggled, the cache will need to be rebuilt.
|
||||
*/
|
||||
/*if (format & GR_TEXFMT_GZ) {
|
||||
dest = _gzdest0;
|
||||
destLen = _gzdestLen;
|
||||
if (dest && destLen) {
|
||||
if (uncompress(dest, &destLen, (*itMap).second->info.data, (*itMap).second->size) != Z_OK) {
|
||||
dest = NULL;
|
||||
destLen = 0;
|
||||
}
|
||||
format &= ~GR_TEXFMT_GZ;
|
||||
}
|
||||
}*/
|
||||
|
||||
if (dest && destLen) {
|
||||
/* texture checksum */
|
||||
gzwrite(gzfp, &((*itMap).first), 8);
|
||||
|
||||
/* other texture info */
|
||||
gzwrite(gzfp, &((*itMap).second->info.width), 4);
|
||||
gzwrite(gzfp, &((*itMap).second->info.height), 4);
|
||||
gzwrite(gzfp, &format, 2);
|
||||
|
||||
gzwrite(gzfp, &((*itMap).second->info.smallLodLog2), 4);
|
||||
gzwrite(gzfp, &((*itMap).second->info.largeLodLog2), 4);
|
||||
gzwrite(gzfp, &((*itMap).second->info.aspectRatioLog2), 4);
|
||||
|
||||
gzwrite(gzfp, &((*itMap).second->info.tiles), 4);
|
||||
gzwrite(gzfp, &((*itMap).second->info.untiled_width), 4);
|
||||
gzwrite(gzfp, &((*itMap).second->info.untiled_height), 4);
|
||||
|
||||
gzwrite(gzfp, &((*itMap).second->info.is_hires_tex), 1);
|
||||
|
||||
gzwrite(gzfp, &destLen, 4);
|
||||
gzwrite(gzfp, dest, destLen);
|
||||
}
|
||||
|
||||
itMap++;
|
||||
|
||||
/* not ready yet */
|
||||
/*if (_callback)
|
||||
(*_callback)(L"Total textures saved to HDD: %d\n", std::distance(itMap, _cache.begin()));*/
|
||||
}
|
||||
gzclose(gzfp);
|
||||
}
|
||||
|
||||
CHDIR(curpath);
|
||||
#endif
|
||||
}
|
||||
return _cache.empty();
|
||||
}
|
||||
|
||||
boolean
|
||||
TxCache::load(const wchar_t *path, const wchar_t *filename, int config)
|
||||
{
|
||||
/* find it on disk */
|
||||
CPath cbuf(stdstr().FromUTF16(path).c_str(),stdstr().FromUTF16(filename).c_str());
|
||||
|
||||
gzFile gzfp = gzopen(cbuf, "rb");
|
||||
DBG_INFO(80, L"gzfp:%x file:%ls\n", gzfp, filename);
|
||||
if (gzfp) {
|
||||
/* yep, we have it. load it into memory cache. */
|
||||
int dataSize;
|
||||
uint64 checksum;
|
||||
GHQTexInfo tmpInfo;
|
||||
int tmpconfig;
|
||||
/* read header to determine config match */
|
||||
gzread(gzfp, &tmpconfig, 4);
|
||||
|
||||
if (tmpconfig == config) {
|
||||
do {
|
||||
memset(&tmpInfo, 0, sizeof(GHQTexInfo));
|
||||
|
||||
gzread(gzfp, &checksum, 8);
|
||||
|
||||
gzread(gzfp, &tmpInfo.width, 4);
|
||||
gzread(gzfp, &tmpInfo.height, 4);
|
||||
gzread(gzfp, &tmpInfo.format, 2);
|
||||
|
||||
gzread(gzfp, &tmpInfo.smallLodLog2, 4);
|
||||
gzread(gzfp, &tmpInfo.largeLodLog2, 4);
|
||||
gzread(gzfp, &tmpInfo.aspectRatioLog2, 4);
|
||||
|
||||
gzread(gzfp, &tmpInfo.tiles, 4);
|
||||
gzread(gzfp, &tmpInfo.untiled_width, 4);
|
||||
gzread(gzfp, &tmpInfo.untiled_height, 4);
|
||||
|
||||
gzread(gzfp, &tmpInfo.is_hires_tex, 1);
|
||||
|
||||
gzread(gzfp, &dataSize, 4);
|
||||
|
||||
tmpInfo.data = (uint8*)malloc(dataSize);
|
||||
if (tmpInfo.data) {
|
||||
gzread(gzfp, tmpInfo.data, dataSize);
|
||||
|
||||
/* add to memory cache */
|
||||
add(checksum, &tmpInfo, (tmpInfo.format & GR_TEXFMT_GZ) ? dataSize : 0);
|
||||
|
||||
free(tmpInfo.data);
|
||||
} else {
|
||||
gzseek(gzfp, dataSize, SEEK_CUR);
|
||||
}
|
||||
|
||||
/* skip in between to prevent the loop from being tied down to vsync */
|
||||
if (_callback && (!(_cache.size() % 100) || gzeof(gzfp)))
|
||||
(*_callback)(L"[%d] total mem:%.02fmb - %ls\n", _cache.size(), (float)_totalSize/1000000, filename);
|
||||
|
||||
} while (!gzeof(gzfp));
|
||||
gzclose(gzfp);
|
||||
}
|
||||
}
|
||||
|
||||
return !_cache.empty();
|
||||
}
|
||||
|
||||
boolean
|
||||
TxCache::del(uint64 checksum)
|
||||
{
|
||||
if (!checksum || _cache.empty()) return 0;
|
||||
|
||||
std::map<uint64, TXCACHE*>::iterator itMap = _cache.find(checksum);
|
||||
if (itMap != _cache.end()) {
|
||||
|
||||
/* for texture cache (not hi-res cache) */
|
||||
if (!_cachelist.empty()) _cachelist.erase(((*itMap).second)->it);
|
||||
|
||||
/* remove from cache */
|
||||
free((*itMap).second->info.data);
|
||||
_totalSize -= (*itMap).second->size;
|
||||
delete (*itMap).second;
|
||||
_cache.erase(itMap);
|
||||
|
||||
DBG_INFO(80, L"removed from cache: checksum = %08X %08X\n", (uint32)(checksum & 0xffffffff), (uint32)(checksum >> 32));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
boolean
|
||||
TxCache::is_cached(uint64 checksum)
|
||||
{
|
||||
std::map<uint64, TXCACHE*>::iterator itMap = _cache.find(checksum);
|
||||
if (itMap != _cache.end()) return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
TxCache::clear()
|
||||
{
|
||||
if (!_cache.empty()) {
|
||||
std::map<uint64, TXCACHE*>::iterator itMap = _cache.begin();
|
||||
while (itMap != _cache.end()) {
|
||||
free((*itMap).second->info.data);
|
||||
delete (*itMap).second;
|
||||
itMap++;
|
||||
}
|
||||
_cache.clear();
|
||||
}
|
||||
|
||||
if (!_cachelist.empty()) _cachelist.clear();
|
||||
|
||||
_totalSize = 0;
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Texture Filtering
|
||||
* Version: 1.0
|
||||
*
|
||||
* Copyright (C) 2007 Hiroshi Morii All Rights Reserved.
|
||||
* Email koolsmoky(at)users.sourceforge.net
|
||||
* Web http://www.3dfxzone.it/koolsmoky
|
||||
*
|
||||
* this 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* this 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __TXCACHE_H__
|
||||
#define __TXCACHE_H__
|
||||
|
||||
#include "TxInternal.h"
|
||||
#include "TxUtil.h"
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
class TxCache
|
||||
{
|
||||
private:
|
||||
std::list<uint64> _cachelist;
|
||||
uint8 *_gzdest0;
|
||||
uint8 *_gzdest1;
|
||||
uint32 _gzdestLen;
|
||||
protected:
|
||||
int _options;
|
||||
std::wstring _ident;
|
||||
std::wstring _path;
|
||||
dispInfoFuncExt _callback;
|
||||
TxUtil *_txUtil;
|
||||
struct TXCACHE {
|
||||
int size;
|
||||
GHQTexInfo info;
|
||||
std::list<uint64>::iterator it;
|
||||
};
|
||||
int _totalSize;
|
||||
int _cacheSize;
|
||||
std::map<uint64, TXCACHE*> _cache;
|
||||
boolean save(const wchar_t *path, const wchar_t *filename, const int config);
|
||||
boolean load(const wchar_t *path, const wchar_t *filename, const int config);
|
||||
boolean del(uint64 checksum); /* checksum hi:palette low:texture */
|
||||
boolean is_cached(uint64 checksum); /* checksum hi:palette low:texture */
|
||||
void clear();
|
||||
public:
|
||||
~TxCache();
|
||||
TxCache(int options, int cachesize, const wchar_t *path, const wchar_t *ident,
|
||||
dispInfoFuncExt callback);
|
||||
boolean add(uint64 checksum, /* checksum hi:palette low:texture */
|
||||
GHQTexInfo *info, int dataSize = 0);
|
||||
boolean get(uint64 checksum, /* checksum hi:palette low:texture */
|
||||
GHQTexInfo *info);
|
||||
};
|
||||
|
||||
#endif /* __TXCACHE_H__ */
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Texture Filtering
|
||||
* Version: 1.0
|
||||
*
|
||||
* Copyright (C) 2007 Hiroshi Morii All Rights Reserved.
|
||||
* Email koolsmoky(at)users.sourceforge.net
|
||||
* Web http://www.3dfxzone.it/koolsmoky
|
||||
*
|
||||
* this 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* this 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#define DBG_LEVEL 80
|
||||
|
||||
#include "TxDbg.h"
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <Common/std string.h>
|
||||
#include <Common/path.h>
|
||||
|
||||
TxDbg::TxDbg()
|
||||
{
|
||||
_level = DBG_LEVEL;
|
||||
CPath Dir(CPath::MODULE_DIRECTORY,"");
|
||||
Dir.AppendDirectory("Logs");
|
||||
|
||||
if (!_dbgfile)
|
||||
#ifdef GHQCHK
|
||||
_dbgfile = fopen(CPath(Dir,"ghqchk.txt"), "w");
|
||||
#else
|
||||
_dbgfile = fopen(CPath((LPCSTR)Dir,"glidehq.dbg"), "w");
|
||||
#endif
|
||||
}
|
||||
|
||||
TxDbg::~TxDbg()
|
||||
{
|
||||
if (_dbgfile) {
|
||||
fclose(_dbgfile);
|
||||
_dbgfile = 0;
|
||||
}
|
||||
|
||||
_level = DBG_LEVEL;
|
||||
}
|
||||
|
||||
void
|
||||
TxDbg::output(const int level, const wchar_t *format, ...)
|
||||
{
|
||||
if (level > _level)
|
||||
return;
|
||||
|
||||
stdstr_f newformat("%d:\t%s",level,stdstr().FromUTF16(format).c_str());
|
||||
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vfwprintf(_dbgfile, newformat.ToUTF16().c_str(), args);
|
||||
fflush(_dbgfile);
|
||||
va_end(args);
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Texture Filtering
|
||||
* Version: 1.0
|
||||
*
|
||||
* Copyright (C) 2007 Hiroshi Morii All Rights Reserved.
|
||||
* Email koolsmoky(at)users.sourceforge.net
|
||||
* Web http://www.3dfxzone.it/koolsmoky
|
||||
*
|
||||
* this 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* this 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __TXDBG_H__
|
||||
#define __TXDBG_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include "TxInternal.h"
|
||||
|
||||
class TxDbg
|
||||
{
|
||||
private:
|
||||
FILE* _dbgfile;
|
||||
int _level;
|
||||
TxDbg();
|
||||
public:
|
||||
static TxDbg* getInstance() {
|
||||
static TxDbg txDbg;
|
||||
return &txDbg;
|
||||
}
|
||||
~TxDbg();
|
||||
void output(const int level, const wchar_t *format, ...);
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DBG_INFO TxDbg::getInstance()->output
|
||||
#define INFO DBG_INFO
|
||||
#else
|
||||
#define DBG_INFO 0 && (wchar_t)
|
||||
#ifdef GHQCHK
|
||||
#define INFO TxDbg::getInstance()->output
|
||||
#else
|
||||
#if 0 /* XXX enable this to log basic hires texture checks */
|
||||
#define INFO TxDbg::getInstance()->output
|
||||
#else
|
||||
#define INFO DBG_INFO
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* __TXDBG_H__ */
|
|
@ -0,0 +1,692 @@
|
|||
/*
|
||||
* Texture Filtering
|
||||
* Version: 1.0
|
||||
*
|
||||
* Copyright (C) 2007 Hiroshi Morii All Rights Reserved.
|
||||
* Email koolsmoky(at)users.sourceforge.net
|
||||
* Web http://www.3dfxzone.it/koolsmoky
|
||||
*
|
||||
* this 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* this 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#pragma warning(disable: 4786)
|
||||
#endif
|
||||
|
||||
#include <common/path.h>
|
||||
#include "TxFilter.h"
|
||||
#include "TextureFilters.h"
|
||||
#include "TxDbg.h"
|
||||
#include "bldno.h"
|
||||
|
||||
void TxFilter::clear()
|
||||
{
|
||||
/* clear hires texture cache */
|
||||
delete _txHiResCache;
|
||||
|
||||
/* clear texture cache */
|
||||
delete _txTexCache;
|
||||
|
||||
/* free memory */
|
||||
TxMemBuf::getInstance()->shutdown();
|
||||
|
||||
/* clear other stuff */
|
||||
delete _txImage;
|
||||
delete _txQuantize;
|
||||
delete _txUtil;
|
||||
}
|
||||
|
||||
TxFilter::~TxFilter()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
TxFilter::TxFilter(int maxwidth, int maxheight, int maxbpp, int options,
|
||||
int cachesize, wchar_t *path, wchar_t *ident,
|
||||
dispInfoFuncExt callback) :
|
||||
_numcore(0),
|
||||
_tex1(NULL),
|
||||
_tex2(NULL),
|
||||
_maxwidth(0),
|
||||
_maxheight(0),
|
||||
_maxbpp(0),
|
||||
_options(0),
|
||||
_cacheSize(0),
|
||||
_txQuantize(NULL),
|
||||
_txTexCache(NULL),
|
||||
_txHiResCache(NULL),
|
||||
_txUtil(NULL),
|
||||
_txImage(NULL),
|
||||
_initialized(false)
|
||||
{
|
||||
/* HACKALERT: the emulator misbehaves and sometimes forgets to shutdown */
|
||||
if ((ident && wcscmp(ident, L"DEFAULT") != 0 && _ident.compare(ident) == 0) &&
|
||||
_maxwidth == maxwidth &&
|
||||
_maxheight == maxheight &&
|
||||
_maxbpp == maxbpp &&
|
||||
_options == options &&
|
||||
_cacheSize == cachesize) return;
|
||||
clear(); /* gcc does not allow the destructor to be called */
|
||||
|
||||
/* shamelessness :P this first call to the debug output message creates
|
||||
* a file in the executable directory. */
|
||||
INFO(0, L"------------------------------------------------------------------\n");
|
||||
#ifdef GHQCHK
|
||||
INFO(0, L" GlideHQ Hires Texture Checker 1.02.00.%d\n", BUILD_NUMBER);
|
||||
#else
|
||||
// INFO(0, L" GlideHQ version 1.02.00.%d\n", BUILD_NUMBER);
|
||||
#endif
|
||||
INFO(0, L" Copyright (C) 2010 Hiroshi Morii All Rights Reserved\n");
|
||||
INFO(0, L" email : koolsmoky(at)users.sourceforge.net\n");
|
||||
INFO(0, L" website : http://www.3dfxzone.it/koolsmoky\n");
|
||||
INFO(0, L"\n");
|
||||
INFO(0, L" Glide64 official website : http://glide64.emuxhaven.net\n");
|
||||
INFO(0, L"------------------------------------------------------------------\n");
|
||||
|
||||
_options = options;
|
||||
|
||||
_txImage = new TxImage();
|
||||
_txQuantize = new TxQuantize();
|
||||
_txUtil = new TxUtil();
|
||||
|
||||
/* get number of CPU cores. */
|
||||
_numcore = _txUtil->getNumberofProcessors();
|
||||
|
||||
_initialized = 0;
|
||||
|
||||
_tex1 = NULL;
|
||||
_tex2 = NULL;
|
||||
|
||||
/* XXX: anything larger than 1024 * 1024 is overkill */
|
||||
_maxwidth = maxwidth > 1024 ? 1024 : maxwidth;
|
||||
_maxheight = maxheight > 1024 ? 1024 : maxheight;
|
||||
_maxbpp = maxbpp;
|
||||
|
||||
_cacheSize = cachesize;
|
||||
|
||||
/* TODO: validate options and do overrides here*/
|
||||
|
||||
/* save path name */
|
||||
if (path)
|
||||
_path.assign(path);
|
||||
|
||||
/* save ROM name */
|
||||
if (ident && wcscmp(ident, L"DEFAULT") != 0)
|
||||
_ident.assign(ident);
|
||||
|
||||
/* check for dxtn extensions */
|
||||
if (!TxLoadLib::getInstance()->getdxtCompressTexFuncExt())
|
||||
_options &= ~S3TC_COMPRESSION;
|
||||
|
||||
if (!TxLoadLib::getInstance()->getfxtCompressTexFuncExt())
|
||||
_options &= ~FXT1_COMPRESSION;
|
||||
|
||||
switch (options & COMPRESSION_MASK) {
|
||||
case FXT1_COMPRESSION:
|
||||
case S3TC_COMPRESSION:
|
||||
break;
|
||||
case NCC_COMPRESSION:
|
||||
default:
|
||||
_options &= ~COMPRESSION_MASK;
|
||||
}
|
||||
|
||||
if (TxMemBuf::getInstance()->init(_maxwidth, _maxheight)) {
|
||||
if (!_tex1)
|
||||
_tex1 = TxMemBuf::getInstance()->get(0);
|
||||
|
||||
if (!_tex2)
|
||||
_tex2 = TxMemBuf::getInstance()->get(1);
|
||||
}
|
||||
|
||||
#if !_16BPP_HACK
|
||||
/* initialize hq4x filter */
|
||||
hq4x_init();
|
||||
#endif
|
||||
|
||||
/* initialize texture cache in bytes. 128Mb will do nicely in most cases */
|
||||
_txTexCache = new TxTexCache(_options, _cacheSize, _path.c_str(), _ident.c_str(), callback);
|
||||
|
||||
/* hires texture */
|
||||
#if HIRES_TEXTURE
|
||||
_txHiResCache = new TxHiResCache(_maxwidth, _maxheight, _maxbpp, _options, _path.c_str(), _ident.c_str(), callback);
|
||||
|
||||
if (_txHiResCache->empty())
|
||||
_options &= ~HIRESTEXTURES_MASK;
|
||||
#endif
|
||||
|
||||
if (!(_options & COMPRESS_TEX))
|
||||
_options &= ~COMPRESSION_MASK;
|
||||
|
||||
if (_tex1 && _tex2)
|
||||
_initialized = 1;
|
||||
}
|
||||
|
||||
boolean
|
||||
TxFilter::filter(uint8 *src, int srcwidth, int srcheight, uint16 srcformat, uint64 g64crc, GHQTexInfo *info)
|
||||
{
|
||||
uint8 *texture = src;
|
||||
uint8 *tmptex = _tex1;
|
||||
uint16 destformat = srcformat;
|
||||
|
||||
/* We need to be initialized first! */
|
||||
if (!_initialized) return 0;
|
||||
|
||||
/* find cached textures */
|
||||
if (_cacheSize) {
|
||||
|
||||
/* calculate checksum of source texture */
|
||||
if (!g64crc)
|
||||
g64crc = (uint64)(_txUtil->checksumTx(texture, srcwidth, srcheight, srcformat));
|
||||
|
||||
DBG_INFO(80, L"filter: crc:%08X %08X %d x %d gfmt:%x\n",
|
||||
(uint32)(g64crc >> 32), (uint32)(g64crc & 0xffffffff), srcwidth, srcheight, srcformat);
|
||||
|
||||
#if 0 /* use hirestex to retrieve cached textures. */
|
||||
/* check if we have it in cache */
|
||||
if (!(g64crc & 0xffffffff00000000) && /* we reach here only when there is no hires texture for this crc */
|
||||
_txTexCache->get(g64crc, info)) {
|
||||
DBG_INFO(80, L"cache hit: %d x %d gfmt:%x\n", info->width, info->height, info->format);
|
||||
return 1; /* yep, we've got it */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Leave small textures alone because filtering makes little difference.
|
||||
* Moreover, some filters require at least 4 * 4 to work.
|
||||
* Bypass _options to do ARGB8888->16bpp if _maxbpp=16 or forced color reduction.
|
||||
*/
|
||||
if ((srcwidth >= 4 && srcheight >= 4) &&
|
||||
((_options & (FILTER_MASK|ENHANCEMENT_MASK|COMPRESSION_MASK)) ||
|
||||
(srcformat == GR_TEXFMT_ARGB_8888 && (_maxbpp < 32 || _options & FORCE16BPP_TEX)))) {
|
||||
|
||||
#if !_16BPP_HACK
|
||||
/* convert textures to a format that the compressor accepts (ARGB8888) */
|
||||
if (_options & COMPRESSION_MASK) {
|
||||
#endif
|
||||
if (srcformat != GR_TEXFMT_ARGB_8888) {
|
||||
if (!_txQuantize->quantize(texture, tmptex, srcwidth, srcheight, srcformat, GR_TEXFMT_ARGB_8888)) {
|
||||
DBG_INFO(80, L"Error: unsupported format! gfmt:%x\n", srcformat);
|
||||
return 0;
|
||||
}
|
||||
texture = tmptex;
|
||||
destformat = GR_TEXFMT_ARGB_8888;
|
||||
}
|
||||
#if !_16BPP_HACK
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (destformat) {
|
||||
case GR_TEXFMT_ARGB_8888:
|
||||
|
||||
/*
|
||||
* prepare texture enhancements (x2, x4 scalers)
|
||||
*/
|
||||
int scale_shift = 0, num_filters = 0;
|
||||
uint32 filter = 0;
|
||||
|
||||
if ((_options & ENHANCEMENT_MASK) == HQ4X_ENHANCEMENT) {
|
||||
if (srcwidth <= (_maxwidth >> 2) && srcheight <= (_maxheight >> 2)) {
|
||||
filter |= HQ4X_ENHANCEMENT;
|
||||
scale_shift = 2;
|
||||
num_filters++;
|
||||
} else if (srcwidth <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) {
|
||||
filter |= HQ2X_ENHANCEMENT;
|
||||
scale_shift = 1;
|
||||
num_filters++;
|
||||
}
|
||||
} else if (_options & ENHANCEMENT_MASK) {
|
||||
if (srcwidth <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) {
|
||||
filter |= (_options & ENHANCEMENT_MASK);
|
||||
scale_shift = 1;
|
||||
num_filters++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* prepare texture filters
|
||||
*/
|
||||
if (_options & (SMOOTH_FILTER_MASK|SHARP_FILTER_MASK)) {
|
||||
filter |= (_options & (SMOOTH_FILTER_MASK|SHARP_FILTER_MASK));
|
||||
num_filters++;
|
||||
}
|
||||
|
||||
/*
|
||||
* execute texture enhancements and filters
|
||||
*/
|
||||
while (num_filters > 0) {
|
||||
|
||||
tmptex = (texture == _tex1) ? _tex2 : _tex1;
|
||||
|
||||
uint8 *_texture = texture;
|
||||
uint8 *_tmptex = tmptex;
|
||||
|
||||
unsigned int numcore = _numcore;
|
||||
unsigned int blkrow = 0;
|
||||
while (numcore > 1 && blkrow == 0) {
|
||||
blkrow = (srcheight >> 2) / numcore;
|
||||
numcore--;
|
||||
}
|
||||
if (blkrow > 0 && numcore > 1) {
|
||||
#ifdef tofix
|
||||
boost::thread *thrd[MAX_NUMCORE];
|
||||
unsigned int i;
|
||||
int blkheight = blkrow << 2;
|
||||
unsigned int srcStride = (srcwidth * blkheight) << 2;
|
||||
unsigned int destStride = srcStride << scale_shift << scale_shift;
|
||||
for (i = 0; i < numcore - 1; i++) {
|
||||
thrd[i] = new boost::thread(boost::bind(filter_8888,
|
||||
(uint32*)_texture,
|
||||
srcwidth,
|
||||
blkheight,
|
||||
(uint32*)_tmptex,
|
||||
filter));
|
||||
_texture += srcStride;
|
||||
_tmptex += destStride;
|
||||
}
|
||||
thrd[i] = new boost::thread(boost::bind(filter_8888,
|
||||
(uint32*)_texture,
|
||||
srcwidth,
|
||||
srcheight - blkheight * i,
|
||||
(uint32*)_tmptex,
|
||||
filter));
|
||||
for (i = 0; i < numcore; i++) {
|
||||
thrd[i]->join();
|
||||
delete thrd[i];
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
filter_8888((uint32*)_texture, srcwidth, srcheight, (uint32*)_tmptex, filter);
|
||||
}
|
||||
|
||||
if (filter & ENHANCEMENT_MASK) {
|
||||
srcwidth <<= scale_shift;
|
||||
srcheight <<= scale_shift;
|
||||
filter &= ~ENHANCEMENT_MASK;
|
||||
scale_shift = 0;
|
||||
}
|
||||
|
||||
texture = tmptex;
|
||||
num_filters--;
|
||||
}
|
||||
|
||||
/*
|
||||
* texture compression
|
||||
*/
|
||||
/* ignored if we only have texture compression option on.
|
||||
* only done when texture enhancer is used. see constructor. */
|
||||
if ((_options & COMPRESSION_MASK) &&
|
||||
(srcwidth >= 64 && srcheight >= 64) /* Texture compression is not suitable for low pixel coarse detail
|
||||
* textures. The assumption here is that textures larger than 64x64
|
||||
* have enough detail to produce decent quality when compressed. The
|
||||
* down side is that narrow stripped textures that the N64 often use
|
||||
* for large background textures are also ignored. It would be more
|
||||
* reasonable if decisions are made based on fourier-transform
|
||||
* spectrum or RMS error.
|
||||
*/
|
||||
) {
|
||||
int compressionType = _options & COMPRESSION_MASK;
|
||||
int tmpwidth, tmpheight;
|
||||
uint16 tmpformat;
|
||||
/* XXX: textures that use 8bit alpha channel look bad with the current
|
||||
* fxt1 library, so we substitute it with dxtn for now. afaik all gfx
|
||||
* cards that support fxt1 also support dxtn. (3dfx and Intel) */
|
||||
if ((destformat == GR_TEXFMT_ALPHA_INTENSITY_88) ||
|
||||
(destformat == GR_TEXFMT_ARGB_8888) ||
|
||||
(destformat == GR_TEXFMT_ALPHA_8)) {
|
||||
compressionType = S3TC_COMPRESSION;
|
||||
}
|
||||
tmptex = (texture == _tex1) ? _tex2 : _tex1;
|
||||
if (_txQuantize->compress(texture, tmptex,
|
||||
srcwidth, srcheight, srcformat,
|
||||
&tmpwidth, &tmpheight, &tmpformat,
|
||||
compressionType)) {
|
||||
srcwidth = tmpwidth;
|
||||
srcheight = tmpheight;
|
||||
destformat = tmpformat;
|
||||
texture = tmptex;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* texture (re)conversions
|
||||
*/
|
||||
if (destformat == GR_TEXFMT_ARGB_8888) {
|
||||
if (srcformat == GR_TEXFMT_ARGB_8888 && (_maxbpp < 32 || _options & FORCE16BPP_TEX)) srcformat = GR_TEXFMT_ARGB_4444;
|
||||
if (srcformat != GR_TEXFMT_ARGB_8888) {
|
||||
tmptex = (texture == _tex1) ? _tex2 : _tex1;
|
||||
if (!_txQuantize->quantize(texture, tmptex, srcwidth, srcheight, GR_TEXFMT_ARGB_8888, srcformat)) {
|
||||
DBG_INFO(80, L"Error: unsupported format! gfmt:%x\n", srcformat);
|
||||
return 0;
|
||||
}
|
||||
texture = tmptex;
|
||||
destformat = srcformat;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
#if !_16BPP_HACK
|
||||
case GR_TEXFMT_ARGB_4444:
|
||||
|
||||
int scale_shift = 0;
|
||||
tmptex = (texture == _tex1) ? _tex2 : _tex1;
|
||||
|
||||
switch (_options & ENHANCEMENT_MASK) {
|
||||
case HQ4X_ENHANCEMENT:
|
||||
if (srcwidth <= (_maxwidth >> 2) && srcheight <= (_maxheight >> 2)) {
|
||||
hq4x_4444((uint8*)texture, (uint8*)tmptex, srcwidth, srcheight, srcwidth, srcwidth * 4 * 2);
|
||||
scale_shift = 2;
|
||||
}/* else if (srcwidth <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) {
|
||||
hq2x_16((uint8*)texture, srcwidth * 2, (uint8*)tmptex, srcwidth * 2 * 2, srcwidth, srcheight);
|
||||
scale_shift = 1;
|
||||
}*/
|
||||
break;
|
||||
case HQ2X_ENHANCEMENT:
|
||||
if (srcwidth <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) {
|
||||
hq2x_16((uint8*)texture, srcwidth * 2, (uint8*)tmptex, srcwidth * 2 * 2, srcwidth, srcheight);
|
||||
scale_shift = 1;
|
||||
}
|
||||
break;
|
||||
case HQ2XS_ENHANCEMENT:
|
||||
if (srcwidth <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) {
|
||||
hq2xS_16((uint8*)texture, srcwidth * 2, (uint8*)tmptex, srcwidth * 2 * 2, srcwidth, srcheight);
|
||||
scale_shift = 1;
|
||||
}
|
||||
break;
|
||||
case LQ2X_ENHANCEMENT:
|
||||
if (srcwidth <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) {
|
||||
lq2x_16((uint8*)texture, srcwidth * 2, (uint8*)tmptex, srcwidth * 2 * 2, srcwidth, srcheight);
|
||||
scale_shift = 1;
|
||||
}
|
||||
break;
|
||||
case LQ2XS_ENHANCEMENT:
|
||||
if (srcwidth <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) {
|
||||
lq2xS_16((uint8*)texture, srcwidth * 2, (uint8*)tmptex, srcwidth * 2 * 2, srcwidth, srcheight);
|
||||
scale_shift = 1;
|
||||
}
|
||||
break;
|
||||
case X2SAI_ENHANCEMENT:
|
||||
if (srcwidth <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) {
|
||||
Super2xSaI_4444((uint16*)texture, (uint16*)tmptex, srcwidth, srcheight, srcwidth);
|
||||
scale_shift = 1;
|
||||
}
|
||||
break;
|
||||
case X2_ENHANCEMENT:
|
||||
if (srcwidth <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) {
|
||||
Texture2x_16((uint8*)texture, srcwidth * 2, (uint8*)tmptex, srcwidth * 2 * 2, srcwidth, srcheight);
|
||||
scale_shift = 1;
|
||||
}
|
||||
}
|
||||
if (scale_shift) {
|
||||
srcwidth <<= scale_shift;
|
||||
srcheight <<= scale_shift;
|
||||
texture = tmptex;
|
||||
}
|
||||
|
||||
if (_options & SMOOTH_FILTER_MASK) {
|
||||
tmptex = (texture == _tex1) ? _tex2 : _tex1;
|
||||
SmoothFilter_4444((uint16*)texture, srcwidth, srcheight, (uint16*)tmptex, (_options & SMOOTH_FILTER_MASK));
|
||||
texture = tmptex;
|
||||
} else if (_options & SHARP_FILTER_MASK) {
|
||||
tmptex = (texture == _tex1) ? _tex2 : _tex1;
|
||||
SharpFilter_4444((uint16*)texture, srcwidth, srcheight, (uint16*)tmptex, (_options & SHARP_FILTER_MASK));
|
||||
texture = tmptex;
|
||||
}
|
||||
|
||||
break;
|
||||
case GR_TEXFMT_ARGB_1555:
|
||||
break;
|
||||
case GR_TEXFMT_RGB_565:
|
||||
break;
|
||||
case GR_TEXFMT_ALPHA_8:
|
||||
break;
|
||||
#endif /* _16BPP_HACK */
|
||||
}
|
||||
}
|
||||
|
||||
/* fill in the texture info. */
|
||||
info->data = texture;
|
||||
info->width = srcwidth;
|
||||
info->height = srcheight;
|
||||
info->format = destformat;
|
||||
info->smallLodLog2 = _txUtil->grLodLog2(srcwidth, srcheight);
|
||||
info->largeLodLog2 = info->smallLodLog2;
|
||||
info->aspectRatioLog2 = _txUtil->grAspectRatioLog2(srcwidth, srcheight);
|
||||
info->is_hires_tex = 0;
|
||||
|
||||
/* cache the texture. */
|
||||
if (_cacheSize) _txTexCache->add(g64crc, info);
|
||||
|
||||
DBG_INFO(80, L"filtered texture: %d x %d gfmt:%x\n", info->width, info->height, info->format);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
boolean
|
||||
TxFilter::hirestex(uint64 g64crc, uint64 r_crc64, uint16 *palette, GHQTexInfo *info)
|
||||
{
|
||||
/* NOTE: Rice CRC32 sometimes return the same value for different textures.
|
||||
* As a workaround, Glide64 CRC32 is used for the key for NON-hires
|
||||
* texture cache.
|
||||
*
|
||||
* r_crc64 = hi:palette low:texture
|
||||
* (separate crc. doesn't necessary have to be rice crc)
|
||||
* g64crc = texture + palette glide64 crc32
|
||||
* (can be any other crc if robust)
|
||||
*/
|
||||
|
||||
DBG_INFO(80, L"hirestex: r_crc64:%08X %08X, g64crc:%08X %08X\n",
|
||||
(uint32)(r_crc64 >> 32), (uint32)(r_crc64 & 0xffffffff),
|
||||
(uint32)(g64crc >> 32), (uint32)(g64crc & 0xffffffff));
|
||||
|
||||
#if HIRES_TEXTURE
|
||||
/* check if we have it in hires memory cache. */
|
||||
if ((_options & HIRESTEXTURES_MASK) && r_crc64) {
|
||||
if (_txHiResCache->get(r_crc64, info)) {
|
||||
DBG_INFO(80, L"hires hit: %d x %d gfmt:%x\n", info->width, info->height, info->format);
|
||||
|
||||
/* TODO: Enable emulation for special N64 combiner modes. There are few ways
|
||||
* to get this done. Also applies for CI textures below.
|
||||
*
|
||||
* Solution 1. Load the hiresolution textures in ARGB8888 (or A8, IA88) format
|
||||
* to cache. When a cache is hit, then we take the modes passed in from Glide64
|
||||
* (also TODO) and apply the modification. Then we do color reduction or format
|
||||
* conversion or compression if desired and stuff it into the non-hires texture
|
||||
* cache.
|
||||
*
|
||||
* Solution 2. When a cache is hit and if the combiner modes are present,
|
||||
* convert the texture to ARGB4444 and pass it back to Glide64 to process.
|
||||
* If a texture is compressed, it needs to be decompressed first. Then add
|
||||
* the processed texture to the non-hires texture cache.
|
||||
*
|
||||
* Solution 3. Hybrid of the above 2. Load the textures in ARGB8888 (A8, IA88)
|
||||
* format. Convert the texture to ARGB4444 and pass it back to Glide64 when
|
||||
* the combiner modes are present. Get the processed texture back from Glide64
|
||||
* and compress if desired and add it to the non-hires texture cache.
|
||||
*
|
||||
* Solution 4. Take the easy way out and forget about this whole thing.
|
||||
*/
|
||||
|
||||
return 1; /* yep, got it */
|
||||
}
|
||||
if (_txHiResCache->get((r_crc64 & 0xffffffff), info)) {
|
||||
DBG_INFO(80, L"hires hit: %d x %d gfmt:%x\n", info->width, info->height, info->format);
|
||||
|
||||
/* for true CI textures, we use the passed in palette to convert to
|
||||
* ARGB1555 and add it to memory cache.
|
||||
*
|
||||
* NOTE: we do this AFTER all other texture cache searches because
|
||||
* only a few texture packs actually use true CI textures.
|
||||
*
|
||||
* NOTE: the pre-converted palette from Glide64 is in RGBA5551 format.
|
||||
* A comp comes before RGB comp.
|
||||
*/
|
||||
if (palette && info->format == GR_TEXFMT_P_8) {
|
||||
DBG_INFO(80, L"found GR_TEXFMT_P_8 format. Need conversion!!\n");
|
||||
|
||||
int width = info->width;
|
||||
int height = info->height;
|
||||
uint16 format = info->format;
|
||||
/* XXX: avoid collision with zlib compression buffer in TxHiResTexture::get */
|
||||
uint8 *texture = info->data;
|
||||
uint8 *tmptex = (texture == _tex1) ? _tex2 : _tex1;
|
||||
|
||||
/* use palette and convert to 16bit format */
|
||||
_txQuantize->P8_16BPP((uint32*)texture, (uint32*)tmptex, info->width, info->height, (uint32*)palette);
|
||||
texture = tmptex;
|
||||
format = GR_TEXFMT_ARGB_1555;
|
||||
|
||||
#if 1
|
||||
/* XXX: compressed if memory cache compression is ON */
|
||||
if (_options & COMPRESSION_MASK) {
|
||||
tmptex = (texture == _tex1) ? _tex2 : _tex1;
|
||||
if (_txQuantize->quantize(texture, tmptex, info->width, info->height, format, GR_TEXFMT_ARGB_8888)) {
|
||||
texture = tmptex;
|
||||
format = GR_TEXFMT_ARGB_8888;
|
||||
}
|
||||
if (format == GR_TEXFMT_ARGB_8888) {
|
||||
tmptex = (texture == _tex1) ? _tex2 : _tex1;
|
||||
if (_txQuantize->compress(texture, tmptex,
|
||||
info->width, info->height, GR_TEXFMT_ARGB_1555,
|
||||
&width, &height, &format,
|
||||
_options & COMPRESSION_MASK)) {
|
||||
texture = tmptex;
|
||||
} else {
|
||||
/*if (!_txQuantize->quantize(texture, tmptex, info->width, info->height, GR_TEXFMT_ARGB_8888, GR_TEXFMT_ARGB_1555)) {
|
||||
DBG_INFO(80, L"Error: unsupported format! gfmt:%x\n", format);
|
||||
return 0;
|
||||
}*/
|
||||
texture = tmptex;
|
||||
format = GR_TEXFMT_ARGB_1555;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* fill in the required info to return */
|
||||
info->data = texture;
|
||||
info->width = width;
|
||||
info->height = height;
|
||||
info->format = format;
|
||||
info->smallLodLog2 = _txUtil->grLodLog2(width, height);
|
||||
info->largeLodLog2 = info->smallLodLog2;
|
||||
info->aspectRatioLog2 = _txUtil->grAspectRatioLog2(width, height);
|
||||
info->is_hires_tex = 1;
|
||||
|
||||
/* XXX: add to hires texture cache!!! */
|
||||
_txHiResCache->add(r_crc64, info);
|
||||
|
||||
DBG_INFO(80, L"GR_TEXFMT_P_8 loaded as gfmt:%x!\n", format);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* check if we have it in memory cache */
|
||||
if (_cacheSize && g64crc) {
|
||||
if (_txTexCache->get(g64crc, info)) {
|
||||
DBG_INFO(80, L"cache hit: %d x %d gfmt:%x\n", info->width, info->height, info->format);
|
||||
return 1; /* yep, we've got it */
|
||||
}
|
||||
}
|
||||
|
||||
DBG_INFO(80, L"no cache hits.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64
|
||||
TxFilter::checksum64(uint8 *src, int width, int height, int size, int rowStride, uint8 *palette)
|
||||
{
|
||||
if (_options & (HIRESTEXTURES_MASK|DUMP_TEX))
|
||||
return _txUtil->checksum64(src, width, height, size, rowStride, palette);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
boolean
|
||||
TxFilter::dmptx(uint8 *src, int width, int height, int rowStridePixel, uint16 gfmt, uint16 n64fmt, uint64 r_crc64)
|
||||
{
|
||||
if (!_initialized)
|
||||
return 0;
|
||||
|
||||
if (!(_options & DUMP_TEX))
|
||||
return 0;
|
||||
|
||||
DBG_INFO(80, L"gfmt = %02x n64fmt = %02x\n", gfmt, n64fmt);
|
||||
DBG_INFO(80, L"hirestex: r_crc64:%08X %08X\n",
|
||||
(uint32)(r_crc64 >> 32), (uint32)(r_crc64 & 0xffffffff));
|
||||
|
||||
if (!_txQuantize->quantize(src, _tex1, rowStridePixel, height, (gfmt & 0x00ff), GR_TEXFMT_ARGB_8888))
|
||||
return 0;
|
||||
|
||||
src = _tex1;
|
||||
|
||||
if (!_path.empty() && !_ident.empty()) {
|
||||
/* dump it to disk */
|
||||
FILE *fp = NULL;
|
||||
CPath tmpbuf(stdstr().FromUTF16(_path.c_str()).c_str(),"");
|
||||
|
||||
/* create directories */
|
||||
tmpbuf.AppendDirectory("texture_dump");
|
||||
|
||||
if (!tmpbuf.DirectoryExists() && !tmpbuf.CreateDirectory())
|
||||
return 0;
|
||||
|
||||
tmpbuf.AppendDirectory(stdstr().FromUTF16(_ident.c_str()).c_str());
|
||||
if (!tmpbuf.DirectoryExists() && !tmpbuf.CreateDirectory())
|
||||
return 0;
|
||||
|
||||
tmpbuf.AppendDirectory("GlideHQ");
|
||||
if (!tmpbuf.DirectoryExists() && !tmpbuf.CreateDirectory())
|
||||
return 0;
|
||||
|
||||
if ((n64fmt >> 8) == 0x2) {
|
||||
tmpbuf.SetNameExtension(stdstr_f("%ls#%08X#%01X#%01X#%08X_ciByRGBA.png",_ident.c_str(),(uint32)(r_crc64 & 0xffffffff), (n64fmt >> 8),(n64fmt & 0xf),(uint32)(r_crc64 >> 32)).c_str());
|
||||
} else {
|
||||
tmpbuf.SetNameExtension(stdstr_f("%ls#%08X#%01X#%01X_all.png",_ident.c_str(),(uint32)(r_crc64 & 0xffffffff),(n64fmt >> 8),(n64fmt & 0xf)).c_str());
|
||||
}
|
||||
#ifdef WIN32
|
||||
if ((fp = fopen(tmpbuf, "wb")) != NULL) {
|
||||
#else
|
||||
char cbuf[MAX_PATH];
|
||||
wcstombs(cbuf, tmpbuf.c_str(), MAX_PATH);
|
||||
if ((fp = fopen(cbuf, "wb")) != NULL) {
|
||||
#endif
|
||||
_txImage->writePNG(src, fp, width, height, (rowStridePixel << 2), 0x0003, 0);
|
||||
fclose(fp);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
boolean
|
||||
TxFilter::reloadhirestex()
|
||||
{
|
||||
DBG_INFO(80, L"Reload hires textures from texture pack.\n");
|
||||
|
||||
if (_txHiResCache->load(0)) {
|
||||
if (_txHiResCache->empty()) _options &= ~HIRESTEXTURES_MASK;
|
||||
else _options |= HIRESTEXTURES_MASK;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Texture Filtering
|
||||
* Version: 1.0
|
||||
*
|
||||
* Copyright (C) 2007 Hiroshi Morii All Rights Reserved.
|
||||
* Email koolsmoky(at)users.sourceforge.net
|
||||
* Web http://www.3dfxzone.it/koolsmoky
|
||||
*
|
||||
* this 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* this 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __TXFILTER_H__
|
||||
#define __TXFILTER_H__
|
||||
|
||||
#include "TxInternal.h"
|
||||
#include "TxQuantize.h"
|
||||
#include "TxHiResCache.h"
|
||||
#include "TxTexCache.h"
|
||||
#include "TxUtil.h"
|
||||
#include "TxImage.h"
|
||||
#include <string>
|
||||
|
||||
class TxFilter
|
||||
{
|
||||
private:
|
||||
int _numcore;
|
||||
|
||||
uint8 *_tex1;
|
||||
uint8 *_tex2;
|
||||
int _maxwidth;
|
||||
int _maxheight;
|
||||
int _maxbpp;
|
||||
int _options;
|
||||
int _cacheSize;
|
||||
std::wstring _ident;
|
||||
std::wstring _path;
|
||||
TxQuantize *_txQuantize;
|
||||
TxTexCache *_txTexCache;
|
||||
TxHiResCache *_txHiResCache;
|
||||
TxUtil *_txUtil;
|
||||
TxImage *_txImage;
|
||||
boolean _initialized;
|
||||
void clear();
|
||||
public:
|
||||
~TxFilter();
|
||||
TxFilter(int maxwidth,
|
||||
int maxheight,
|
||||
int maxbpp,
|
||||
int options,
|
||||
int cachesize,
|
||||
wchar_t *path,
|
||||
wchar_t *ident,
|
||||
dispInfoFuncExt callback);
|
||||
boolean filter(uint8 *src,
|
||||
int srcwidth,
|
||||
int srcheight,
|
||||
uint16 srcformat,
|
||||
uint64 g64crc, /* glide64 crc, 64bit for future use */
|
||||
GHQTexInfo *info);
|
||||
boolean hirestex(uint64 g64crc, /* glide64 crc, 64bit for future use */
|
||||
uint64 r_crc64, /* checksum hi:palette low:texture */
|
||||
uint16 *palette,
|
||||
GHQTexInfo *info);
|
||||
uint64 checksum64(uint8 *src, int width, int height, int size, int rowStride, uint8 *palette);
|
||||
boolean dmptx(uint8 *src, int width, int height, int rowStridePixel, uint16 gfmt, uint16 n64fmt, uint64 r_crc64);
|
||||
boolean reloadhirestex();
|
||||
};
|
||||
|
||||
#endif /* __TXFILTER_H__ */
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Texture Filtering
|
||||
* Version: 1.0
|
||||
*
|
||||
* Copyright (C) 2007 Hiroshi Morii All Rights Reserved.
|
||||
* Email koolsmoky(at)users.sourceforge.net
|
||||
* Web http://www.3dfxzone.it/koolsmoky
|
||||
*
|
||||
* this 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* this 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#pragma warning(disable: 4786)
|
||||
#endif
|
||||
|
||||
#include "TxFilter.h"
|
||||
|
||||
TxFilter *txFilter = NULL;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
TAPI boolean TAPIENTRY
|
||||
txfilter_init(int maxwidth, int maxheight, int maxbpp, int options, int cachesize,
|
||||
wchar_t *path, wchar_t*ident,
|
||||
dispInfoFuncExt callback)
|
||||
{
|
||||
if (txFilter) return 0;
|
||||
|
||||
txFilter = new TxFilter(maxwidth, maxheight, maxbpp, options, cachesize,
|
||||
path, ident, callback);
|
||||
|
||||
return (txFilter ? 1 : 0);
|
||||
}
|
||||
|
||||
void txfilter_shutdown(void)
|
||||
{
|
||||
if (txFilter) delete txFilter;
|
||||
|
||||
txFilter = NULL;
|
||||
}
|
||||
|
||||
TAPI boolean TAPIENTRY
|
||||
txfilter(uint8 *src, int srcwidth, int srcheight, uint16 srcformat,
|
||||
uint64 g64crc, GHQTexInfo *info)
|
||||
{
|
||||
if (txFilter)
|
||||
return txFilter->filter(src, srcwidth, srcheight, srcformat,
|
||||
g64crc, info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
TAPI boolean TAPIENTRY
|
||||
txfilter_hirestex(uint64 g64crc, uint64 r_crc64, uint16 *palette, GHQTexInfo *info)
|
||||
{
|
||||
if (txFilter)
|
||||
return txFilter->hirestex(g64crc, r_crc64, palette, info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
TAPI uint64 TAPIENTRY
|
||||
txfilter_checksum(uint8 *src, int width, int height, int size, int rowStride, uint8 *palette)
|
||||
{
|
||||
if (txFilter)
|
||||
return txFilter->checksum64(src, width, height, size, rowStride, palette);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
TAPI boolean TAPIENTRY
|
||||
txfilter_dmptx(uint8 *src, int width, int height, int rowStridePixel, uint16 gfmt, uint16 n64fmt, uint64 r_crc64)
|
||||
{
|
||||
if (txFilter)
|
||||
return txFilter->dmptx(src, width, height, rowStridePixel, gfmt, n64fmt, r_crc64);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
TAPI boolean TAPIENTRY
|
||||
txfilter_reloadhirestex()
|
||||
{
|
||||
if (txFilter)
|
||||
return txFilter->reloadhirestex();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Texture Filtering
|
||||
* Version: 1.0
|
||||
*
|
||||
* Copyright (C) 2007 Hiroshi Morii All Rights Reserved.
|
||||
* Email koolsmoky(at)users.sourceforge.net
|
||||
* Web http://www.3dfxzone.it/koolsmoky
|
||||
*
|
||||
* this 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* this 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __TXHIRESCACHE_H__
|
||||
#define __TXHIRESCACHE_H__
|
||||
|
||||
/* support hires textures
|
||||
* 0: disable
|
||||
* 1: enable
|
||||
*/
|
||||
#define HIRES_TEXTURE 1
|
||||
|
||||
#include "TxCache.h"
|
||||
#include "TxQuantize.h"
|
||||
#include "TxImage.h"
|
||||
#include "TxReSample.h"
|
||||
|
||||
class TxHiResCache : public TxCache
|
||||
{
|
||||
private:
|
||||
int _maxwidth;
|
||||
int _maxheight;
|
||||
int _maxbpp;
|
||||
boolean _haveCache;
|
||||
boolean _abortLoad;
|
||||
TxImage *_txImage;
|
||||
TxQuantize *_txQuantize;
|
||||
TxReSample *_txReSample;
|
||||
boolean loadHiResTextures(LPCSTR dir_path, boolean replace);
|
||||
public:
|
||||
~TxHiResCache();
|
||||
TxHiResCache(int maxwidth, int maxheight, int maxbpp, int options,
|
||||
const wchar_t *path, const wchar_t *ident,
|
||||
dispInfoFuncExt callback);
|
||||
boolean empty();
|
||||
boolean load(boolean replace);
|
||||
};
|
||||
|
||||
#endif /* __TXHIRESCACHE_H__ */
|
|
@ -0,0 +1,799 @@
|
|||
/*
|
||||
* Texture Filtering
|
||||
* Version: 1.0
|
||||
*
|
||||
* Copyright (C) 2007 Hiroshi Morii All Rights Reserved.
|
||||
* Email koolsmoky(at)users.sourceforge.net
|
||||
* Web http://www.3dfxzone.it/koolsmoky
|
||||
*
|
||||
* this 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* this 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/* use power of 2 texture size
|
||||
* (0:disable, 1:enable, 2:3dfx) */
|
||||
#define POW2_TEXTURES 0
|
||||
|
||||
/* check 8 bytes. use a larger value if needed. */
|
||||
#define PNG_CHK_BYTES 8
|
||||
|
||||
#include "TxImage.h"
|
||||
#include "TxReSample.h"
|
||||
#include "TxDbg.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
boolean
|
||||
TxImage::getPNGInfo(FILE *fp, png_structp *png_ptr, png_infop *info_ptr)
|
||||
{
|
||||
unsigned char sig[PNG_CHK_BYTES];
|
||||
|
||||
/* check for valid file pointer */
|
||||
if (!fp)
|
||||
return 0;
|
||||
|
||||
/* check if file is PNG */
|
||||
if (fread(sig, 1, PNG_CHK_BYTES, fp) != PNG_CHK_BYTES)
|
||||
return 0;
|
||||
|
||||
if (png_sig_cmp(sig, 0, PNG_CHK_BYTES) != 0)
|
||||
return 0;
|
||||
|
||||
/* get PNG file info */
|
||||
*png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if (!*png_ptr)
|
||||
return 0;
|
||||
|
||||
*info_ptr = png_create_info_struct(*png_ptr);
|
||||
if (!*info_ptr) {
|
||||
png_destroy_read_struct(png_ptr, NULL, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (setjmp(png_jmpbuf(*png_ptr))) {
|
||||
DBG_INFO(80, L"error reading png!\n");
|
||||
png_destroy_read_struct(png_ptr, info_ptr, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
png_init_io(*png_ptr, fp);
|
||||
png_set_sig_bytes(*png_ptr, PNG_CHK_BYTES);
|
||||
png_read_info(*png_ptr, *info_ptr);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8*
|
||||
TxImage::readPNG(FILE* fp, int* width, int* height, uint16* format)
|
||||
{
|
||||
/* NOTE: returned image format is GR_TEXFMT_ARGB_8888 */
|
||||
|
||||
png_structp png_ptr;
|
||||
png_infop info_ptr;
|
||||
uint8 *image = NULL;
|
||||
int bit_depth, color_type, interlace_type, compression_type, filter_type,
|
||||
row_bytes, o_width, o_height, num_pas;
|
||||
|
||||
/* initialize */
|
||||
*width = 0;
|
||||
*height = 0;
|
||||
*format = 0;
|
||||
|
||||
/* check if we have a valid png file */
|
||||
if (!fp)
|
||||
return NULL;
|
||||
|
||||
if (!getPNGInfo(fp, &png_ptr, &info_ptr)) {
|
||||
INFO(80, L"error reading png file! png image is corrupt.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
png_get_IHDR(png_ptr, info_ptr,
|
||||
(png_uint_32*)&o_width, (png_uint_32*)&o_height, &bit_depth, &color_type,
|
||||
&interlace_type, &compression_type, &filter_type);
|
||||
|
||||
DBG_INFO(80, L"png format %d x %d bitdepth:%d color:%x interlace:%x compression:%x filter:%x\n",
|
||||
o_width, o_height, bit_depth, color_type,
|
||||
interlace_type, compression_type, filter_type);
|
||||
|
||||
/* transformations */
|
||||
|
||||
/* Rice hi-res textures
|
||||
* _all.png
|
||||
* _rgb.png, _a.png
|
||||
* _ciByRGBA.png
|
||||
* _allciByRGBA.png
|
||||
*/
|
||||
|
||||
/* strip if color channel is larger than 8 bits */
|
||||
if (bit_depth > 8) {
|
||||
png_set_strip_16(png_ptr);
|
||||
bit_depth = 8;
|
||||
}
|
||||
|
||||
#if 1
|
||||
/* These are not really required per Rice format spec,
|
||||
* but is done just in case someone uses them.
|
||||
*/
|
||||
/* convert palette color to rgb color */
|
||||
if (color_type == PNG_COLOR_TYPE_PALETTE) {
|
||||
png_set_palette_to_rgb(png_ptr);
|
||||
color_type = PNG_COLOR_TYPE_RGB;
|
||||
}
|
||||
|
||||
/* expand 1,2,4 bit gray scale to 8 bit gray scale */
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
|
||||
png_set_expand_gray_1_2_4_to_8(png_ptr);
|
||||
|
||||
/* convert gray scale or gray scale + alpha to rgb color */
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY ||
|
||||
color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
|
||||
png_set_gray_to_rgb(png_ptr);
|
||||
color_type = PNG_COLOR_TYPE_RGB;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* add alpha channel if any */
|
||||
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
|
||||
png_set_tRNS_to_alpha(png_ptr);
|
||||
color_type = PNG_COLOR_TYPE_RGB_ALPHA;
|
||||
}
|
||||
|
||||
/* convert rgb to rgba */
|
||||
if (color_type == PNG_COLOR_TYPE_RGB) {
|
||||
png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
|
||||
color_type = PNG_COLOR_TYPE_RGB_ALPHA;
|
||||
}
|
||||
|
||||
/* punt invalid formats */
|
||||
if (color_type != PNG_COLOR_TYPE_RGB_ALPHA) {
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
DBG_INFO(80, L"Error: not PNG_COLOR_TYPE_RGB_ALPHA format!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*png_color_8p sig_bit;
|
||||
if (png_get_sBIT(png_ptr, info_ptr, &sig_bit))
|
||||
png_set_shift(png_ptr, sig_bit);*/
|
||||
|
||||
/* convert rgba to bgra */
|
||||
png_set_bgr(png_ptr);
|
||||
|
||||
/* turn on interlace handling to cope with the weirdness
|
||||
* of texture authors using interlaced format */
|
||||
num_pas = png_set_interlace_handling(png_ptr);
|
||||
|
||||
/* update info structure */
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
|
||||
/* we only get here if ARGB8888 */
|
||||
row_bytes = png_get_rowbytes(png_ptr, info_ptr);
|
||||
|
||||
/* allocate memory to read in image */
|
||||
image = (uint8*)malloc(row_bytes * o_height);
|
||||
|
||||
/* read in image */
|
||||
if (image) {
|
||||
int pas, i;
|
||||
uint8* tmpimage;
|
||||
|
||||
for (pas = 0; pas < num_pas; pas++) { /* deal with interlacing */
|
||||
tmpimage = image;
|
||||
|
||||
for (i = 0; i < o_height; i++) {
|
||||
/* copy row */
|
||||
png_read_rows(png_ptr, &tmpimage, NULL, 1);
|
||||
tmpimage += row_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
/* read rest of the info structure */
|
||||
png_read_end(png_ptr, info_ptr);
|
||||
|
||||
*width = (row_bytes >> 2);
|
||||
*height = o_height;
|
||||
*format = GR_TEXFMT_ARGB_8888;
|
||||
|
||||
#if POW2_TEXTURES
|
||||
/* next power of 2 size conversions */
|
||||
/* NOTE: I can do this in the above loop for faster operations, but some
|
||||
* texture packs require a workaround. see HACKALERT in nextPow2().
|
||||
*/
|
||||
|
||||
TxReSample txReSample = new TxReSample; // XXX: temporary. move to a better place.
|
||||
|
||||
#if (POW2_TEXTURES == 2)
|
||||
if (!txReSample->nextPow2(&image, width, height, 32, 1)) {
|
||||
#else
|
||||
if (!txReSample->nextPow2(&image, width, height, 32, 0)) {
|
||||
#endif
|
||||
if (image) {
|
||||
free(image);
|
||||
image = NULL;
|
||||
}
|
||||
*width = 0;
|
||||
*height = 0;
|
||||
*format = 0;
|
||||
}
|
||||
|
||||
delete txReSample;
|
||||
|
||||
#endif /* POW2_TEXTURES */
|
||||
}
|
||||
|
||||
/* clean up */
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (!image) {
|
||||
DBG_INFO(80, L"Error: failed to load png image!\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
boolean
|
||||
TxImage::writePNG(uint8* src, FILE* fp, int width, int height, int rowStride, uint16 format, uint8 *palette)
|
||||
{
|
||||
png_structp png_ptr;
|
||||
png_infop info_ptr;
|
||||
png_color_8 sig_bit;
|
||||
png_colorp palette_ptr;
|
||||
png_bytep trans_ptr;//, tex_ptr;
|
||||
int bit_depth, color_type, row_bytes, num_palette;
|
||||
int i;
|
||||
//uint16 srcfmt, destfmt;
|
||||
|
||||
if (!src || !fp)
|
||||
return 0;
|
||||
|
||||
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if (png_ptr == NULL)
|
||||
return 0;
|
||||
|
||||
info_ptr = png_create_info_struct(png_ptr);
|
||||
if (info_ptr == NULL) {
|
||||
png_destroy_write_struct(&png_ptr, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*if (setjmp(png_ptr->jmpbuf)) {
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
return 0;
|
||||
}*/
|
||||
|
||||
png_init_io(png_ptr, fp);
|
||||
|
||||
/* TODO: images must be converted to RGBA8888 or CI8,
|
||||
* palettes need to be separated to A and RGB. */
|
||||
|
||||
/* N64 formats
|
||||
* Format: 0 - RGBA, 1 - YUV, 2 - CI, 3 - IA, 4 - I
|
||||
* Size: 0 - 4bit, 1 - 8bit, 2 - 16bit, 3 - 32 bit
|
||||
* format = (Format << 8 | Size);
|
||||
*/
|
||||
|
||||
/* each channel is saved in 8bits for consistency */
|
||||
switch (format) {
|
||||
case 0x0002:/* RGBA5551 */
|
||||
bit_depth = 8;
|
||||
sig_bit.red = 5;
|
||||
sig_bit.green = 5;
|
||||
sig_bit.blue = 5;
|
||||
sig_bit.alpha = 1;
|
||||
color_type = PNG_COLOR_TYPE_RGB_ALPHA;
|
||||
break;
|
||||
case 0x0003:/* RGBA8888 */
|
||||
case 0x0302:/* IA88 */
|
||||
bit_depth = 8;
|
||||
sig_bit.red = 8;
|
||||
sig_bit.green = 8;
|
||||
sig_bit.blue = 8;
|
||||
sig_bit.alpha = 8;
|
||||
color_type = PNG_COLOR_TYPE_RGB_ALPHA;
|
||||
break;
|
||||
case 0x0300:/* IA31 */
|
||||
bit_depth = 8;
|
||||
sig_bit.red = 3;
|
||||
sig_bit.green = 3;
|
||||
sig_bit.blue = 3;
|
||||
sig_bit.alpha = 1;
|
||||
color_type = PNG_COLOR_TYPE_RGB_ALPHA;
|
||||
break;
|
||||
case 0x0301:/* IA44 */
|
||||
bit_depth = 8;
|
||||
sig_bit.red = 4;
|
||||
sig_bit.green = 4;
|
||||
sig_bit.blue = 4;
|
||||
sig_bit.alpha = 4;
|
||||
color_type = PNG_COLOR_TYPE_RGB_ALPHA;
|
||||
break;
|
||||
case 0x0400:/* I4 */
|
||||
bit_depth = 8;
|
||||
sig_bit.red = 4;
|
||||
sig_bit.green = 4;
|
||||
sig_bit.blue = 4;
|
||||
color_type = PNG_COLOR_TYPE_RGB;
|
||||
break;
|
||||
case 0x0401:/* I8 */
|
||||
case 0x0402:/* I16 */
|
||||
bit_depth = 8;
|
||||
sig_bit.red = 8;
|
||||
sig_bit.green = 8;
|
||||
sig_bit.blue = 8;
|
||||
color_type = PNG_COLOR_TYPE_RGB;
|
||||
break;
|
||||
case 0x0200:/* CI4 */
|
||||
bit_depth = 8;
|
||||
num_palette = 16;
|
||||
color_type = PNG_COLOR_TYPE_PALETTE;
|
||||
break;
|
||||
case 0x0201:/* CI8 */
|
||||
bit_depth = 8;
|
||||
num_palette = 256;
|
||||
color_type = PNG_COLOR_TYPE_PALETTE;
|
||||
break;
|
||||
case 0x0102:/* YUV ? */
|
||||
case 0x0103:
|
||||
default:
|
||||
/* unsupported format */
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (color_type) {
|
||||
case PNG_COLOR_TYPE_RGB_ALPHA:
|
||||
case PNG_COLOR_TYPE_RGB:
|
||||
//row_bytes = (bit_depth * width) >> 1;
|
||||
row_bytes = rowStride;
|
||||
png_set_bgr(png_ptr);
|
||||
png_set_sBIT(png_ptr, info_ptr, &sig_bit);
|
||||
break;
|
||||
case PNG_COLOR_TYPE_PALETTE:
|
||||
//row_bytes = (bit_depth * width) >> 3;
|
||||
row_bytes = rowStride;
|
||||
png_set_PLTE(png_ptr, info_ptr, palette_ptr, num_palette);
|
||||
png_set_tRNS(png_ptr, info_ptr, trans_ptr, num_palette, 0);
|
||||
}
|
||||
|
||||
//png_set_filter(png_ptr, 0, PNG_ALL_FILTERS);
|
||||
|
||||
//if (bit_depth == 16)
|
||||
// png_set_swap(png_ptr);
|
||||
|
||||
//if (bit_depth < 8)
|
||||
// png_set_packswap(png_ptr);
|
||||
|
||||
png_set_IHDR(png_ptr, info_ptr, width, height,
|
||||
bit_depth, color_type, PNG_INTERLACE_NONE,
|
||||
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
||||
|
||||
//png_set_gAMA(png_ptr, info_ptr, 1.0);
|
||||
|
||||
png_write_info(png_ptr, info_ptr);
|
||||
for (i = 0; i < height; i++) {
|
||||
png_write_row(png_ptr, (png_bytep)src);
|
||||
src += row_bytes;
|
||||
}
|
||||
png_write_end(png_ptr, info_ptr);
|
||||
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
|
||||
//if (tex_ptr) delete [] tex_ptr;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
boolean
|
||||
TxImage::getBMPInfo(FILE* fp, BITMAPFILEHEADER* bmp_fhdr, BITMAPINFOHEADER* bmp_ihdr)
|
||||
{
|
||||
/*
|
||||
* read in BITMAPFILEHEADER
|
||||
*/
|
||||
|
||||
/* is this a BMP file? */
|
||||
if (fread(&bmp_fhdr->bfType, 2, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
if (memcmp(&bmp_fhdr->bfType, "BM", 2) != 0)
|
||||
return 0;
|
||||
|
||||
/* get file size */
|
||||
if (fread(&bmp_fhdr->bfSize, 4, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
/* reserved 1 */
|
||||
if (fread(&bmp_fhdr->bfReserved1, 2, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
/* reserved 2 */
|
||||
if (fread(&bmp_fhdr->bfReserved2, 2, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
/* offset to the image data */
|
||||
if (fread(&bmp_fhdr->bfOffBits, 4, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* read in BITMAPINFOHEADER
|
||||
*/
|
||||
|
||||
/* size of BITMAPINFOHEADER */
|
||||
if (fread(&bmp_ihdr->biSize, 4, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
/* is this a Windows BMP? */
|
||||
if (bmp_ihdr->biSize != 40)
|
||||
return 0;
|
||||
|
||||
/* width of the bitmap in pixels */
|
||||
if (fread(&bmp_ihdr->biWidth, 4, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
/* height of the bitmap in pixels */
|
||||
if (fread(&bmp_ihdr->biHeight, 4, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
/* number of planes (always 1) */
|
||||
if (fread(&bmp_ihdr->biPlanes, 2, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
/* number of bits-per-pixel. (1, 4, 8, 16, 24, 32) */
|
||||
if (fread(&bmp_ihdr->biBitCount, 2, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
/* compression for a compressed bottom-up bitmap
|
||||
* 0 : uncompressed format
|
||||
* 1 : run-length encoded 4 bpp format
|
||||
* 2 : run-length encoded 8 bpp format
|
||||
* 3 : bitfield
|
||||
*/
|
||||
if (fread(&bmp_ihdr->biCompression, 4, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
/* size of the image in bytes */
|
||||
if (fread(&bmp_ihdr->biSizeImage, 4, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
/* horizontal resolution in pixels-per-meter */
|
||||
if (fread(&bmp_ihdr->biXPelsPerMeter, 4, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
/* vertical resolution in pixels-per-meter */
|
||||
if (fread(&bmp_ihdr->biYPelsPerMeter, 4, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
/* number of color indexes in the color table that are actually used */
|
||||
if (fread(&bmp_ihdr->biClrUsed, 4, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
/* the number of color indexes that are required for displaying */
|
||||
if (fread(&bmp_ihdr->biClrImportant, 4, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8*
|
||||
TxImage::readBMP(FILE* fp, int* width, int* height, uint16* format)
|
||||
{
|
||||
/* NOTE: returned image format;
|
||||
* 4, 8bit palette bmp -> GR_TEXFMT_P_8
|
||||
* 24, 32bit bmp -> GR_TEXFMT_ARGB_8888
|
||||
*/
|
||||
|
||||
uint8 *image = NULL;
|
||||
uint8 *image_row = NULL;
|
||||
uint8 *tmpimage = NULL;
|
||||
int row_bytes, pos, i, j;
|
||||
/* Windows Bitmap */
|
||||
BITMAPFILEHEADER bmp_fhdr;
|
||||
BITMAPINFOHEADER bmp_ihdr;
|
||||
|
||||
/* initialize */
|
||||
*width = 0;
|
||||
*height = 0;
|
||||
*format = 0;
|
||||
|
||||
/* check if we have a valid bmp file */
|
||||
if (!fp)
|
||||
return NULL;
|
||||
|
||||
if (!getBMPInfo(fp, &bmp_fhdr, &bmp_ihdr)) {
|
||||
INFO(80, L"error reading bitmap file! bitmap image is corrupt.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DBG_INFO(80, L"bmp format %d x %d bitdepth:%d compression:%x offset:%d\n",
|
||||
bmp_ihdr.biWidth, bmp_ihdr.biHeight, bmp_ihdr.biBitCount,
|
||||
bmp_ihdr.biCompression, bmp_fhdr.bfOffBits);
|
||||
|
||||
/* rowStride in bytes */
|
||||
row_bytes = (bmp_ihdr.biWidth * bmp_ihdr.biBitCount) >> 3;
|
||||
/* align to 4bytes boundary */
|
||||
row_bytes = (row_bytes + 3) & ~3;
|
||||
|
||||
/* Rice hi-res textures */
|
||||
if (!(bmp_ihdr.biBitCount == 8 || bmp_ihdr.biBitCount == 4 || bmp_ihdr.biBitCount == 32 || bmp_ihdr.biBitCount == 24) ||
|
||||
bmp_ihdr.biCompression != 0) {
|
||||
DBG_INFO(80, L"Error: incompatible bitmap format!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (bmp_ihdr.biBitCount) {
|
||||
case 8:
|
||||
case 32:
|
||||
/* 8 bit, 32 bit bitmap */
|
||||
image = (uint8*)malloc(row_bytes * bmp_ihdr.biHeight);
|
||||
if (image) {
|
||||
tmpimage = image;
|
||||
pos = bmp_fhdr.bfOffBits + row_bytes * (bmp_ihdr.biHeight - 1);
|
||||
for (i = 0; i < bmp_ihdr.biHeight; i++) {
|
||||
/* read in image */
|
||||
fseek(fp, pos, SEEK_SET);
|
||||
fread(tmpimage, row_bytes, 1, fp);
|
||||
tmpimage += row_bytes;
|
||||
pos -= row_bytes;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
/* 4bit bitmap */
|
||||
image = (uint8*)malloc((row_bytes * bmp_ihdr.biHeight) << 1);
|
||||
image_row = (uint8*)malloc(row_bytes);
|
||||
if (image && image_row) {
|
||||
tmpimage = image;
|
||||
pos = bmp_fhdr.bfOffBits + row_bytes * (bmp_ihdr.biHeight - 1);
|
||||
for (i = 0; i < bmp_ihdr.biHeight; i++) {
|
||||
/* read in image */
|
||||
fseek(fp, pos, SEEK_SET);
|
||||
fread(image_row, row_bytes, 1, fp);
|
||||
/* expand 4bpp to 8bpp. stuff 4bit values into 8bit comps. */
|
||||
for (j = 0; j < row_bytes; j++) {
|
||||
tmpimage[j << 1] = image_row[j] & 0x0f;
|
||||
tmpimage[(j << 1) + 1] = (image_row[j] & 0xf0) >> 4;
|
||||
}
|
||||
tmpimage += (row_bytes << 1);
|
||||
pos -= row_bytes;
|
||||
}
|
||||
free(image_row);
|
||||
} else {
|
||||
if (image_row) free(image_row);
|
||||
if (image) free(image);
|
||||
image = NULL;
|
||||
}
|
||||
break;
|
||||
case 24:
|
||||
/* 24 bit bitmap */
|
||||
image = (uint8*)malloc((bmp_ihdr.biWidth * bmp_ihdr.biHeight) << 2);
|
||||
image_row = (uint8*)malloc(row_bytes);
|
||||
if (image && image_row) {
|
||||
tmpimage = image;
|
||||
pos = bmp_fhdr.bfOffBits + row_bytes * (bmp_ihdr.biHeight - 1);
|
||||
for (i = 0; i < bmp_ihdr.biHeight; i++) {
|
||||
/* read in image */
|
||||
fseek(fp, pos, SEEK_SET);
|
||||
fread(image_row, row_bytes, 1, fp);
|
||||
/* convert 24bpp to 32bpp. */
|
||||
for (j = 0; j < bmp_ihdr.biWidth; j++) {
|
||||
tmpimage[(j << 2)] = image_row[j * 3];
|
||||
tmpimage[(j << 2) + 1] = image_row[j * 3 + 1];
|
||||
tmpimage[(j << 2) + 2] = image_row[j * 3 + 2];
|
||||
tmpimage[(j << 2) + 3] = 0xFF;
|
||||
}
|
||||
tmpimage += (bmp_ihdr.biWidth << 2);
|
||||
pos -= row_bytes;
|
||||
}
|
||||
free(image_row);
|
||||
} else {
|
||||
if (image_row) free(image_row);
|
||||
if (image) free(image);
|
||||
image = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (image) {
|
||||
*width = (row_bytes << 3) / bmp_ihdr.biBitCount;
|
||||
*height = bmp_ihdr.biHeight;
|
||||
|
||||
switch (bmp_ihdr.biBitCount) {
|
||||
case 8:
|
||||
case 4:
|
||||
*format = GR_TEXFMT_P_8;
|
||||
break;
|
||||
case 32:
|
||||
case 24:
|
||||
*format = GR_TEXFMT_ARGB_8888;
|
||||
}
|
||||
|
||||
#if POW2_TEXTURES
|
||||
/* next power of 2 size conversions */
|
||||
/* NOTE: I can do this in the above loop for faster operations, but some
|
||||
* texture packs require a workaround. see HACKALERT in nextPow2().
|
||||
*/
|
||||
|
||||
TxReSample txReSample = new TxReSample; // XXX: temporary. move to a better place.
|
||||
|
||||
#if (POW2_TEXTURES == 2)
|
||||
if (!txReSample->nextPow2(&image, width, height, 8, 1)) {
|
||||
#else
|
||||
if (!txReSample->nextPow2(&image, width, height, 8, 0)) {
|
||||
#endif
|
||||
if (image) {
|
||||
free(image);
|
||||
image = NULL;
|
||||
}
|
||||
*width = 0;
|
||||
*height = 0;
|
||||
*format = 0;
|
||||
}
|
||||
|
||||
delete txReSample;
|
||||
|
||||
#endif /* POW2_TEXTURES */
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (!image) {
|
||||
DBG_INFO(80, L"Error: failed to load bmp image!\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
boolean
|
||||
TxImage::getDDSInfo(FILE *fp, DDSFILEHEADER *dds_fhdr)
|
||||
{
|
||||
/*
|
||||
* read in DDSFILEHEADER
|
||||
*/
|
||||
|
||||
/* is this a DDS file? */
|
||||
if (fread(&dds_fhdr->dwMagic, 4, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
if (memcmp(&dds_fhdr->dwMagic, "DDS ", 4) != 0)
|
||||
return 0;
|
||||
|
||||
if (fread(&dds_fhdr->dwSize, 4, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
/* get file flags */
|
||||
if (fread(&dds_fhdr->dwFlags, 4, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
/* height of dds in pixels */
|
||||
if (fread(&dds_fhdr->dwHeight, 4, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
/* width of dds in pixels */
|
||||
if (fread(&dds_fhdr->dwWidth, 4, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
if (fread(&dds_fhdr->dwLinearSize, 4, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
if (fread(&dds_fhdr->dwDepth, 4, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
if (fread(&dds_fhdr->dwMipMapCount, 4, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
if (fread(&dds_fhdr->dwReserved1, 4 * 11, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
if (fread(&dds_fhdr->ddpf.dwSize, 4, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
if (fread(&dds_fhdr->ddpf.dwFlags, 4, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
if (fread(&dds_fhdr->ddpf.dwFourCC, 4, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
if (fread(&dds_fhdr->ddpf.dwRGBBitCount, 4, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
if (fread(&dds_fhdr->ddpf.dwRBitMask, 4, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
if (fread(&dds_fhdr->ddpf.dwGBitMask, 4, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
if (fread(&dds_fhdr->ddpf.dwBBitMask, 4, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
if (fread(&dds_fhdr->ddpf.dwRGBAlphaBitMask, 4, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
if (fread(&dds_fhdr->dwCaps1, 4, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
if (fread(&dds_fhdr->dwCaps2, 4, 1, fp) != 1)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8*
|
||||
TxImage::readDDS(FILE* fp, int* width, int* height, uint16* format)
|
||||
{
|
||||
uint8 *image = NULL;
|
||||
DDSFILEHEADER dds_fhdr;
|
||||
uint16 tmpformat = 0;
|
||||
|
||||
/* initialize */
|
||||
*width = 0;
|
||||
*height = 0;
|
||||
*format = 0;
|
||||
|
||||
/* check if we have a valid dds file */
|
||||
if (!fp)
|
||||
return NULL;
|
||||
|
||||
if (!getDDSInfo(fp, &dds_fhdr)) {
|
||||
INFO(80, L"error reading dds file! dds image is corrupt.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DBG_INFO(80, L"dds format %d x %d HeaderSize %d LinearSize %d\n",
|
||||
dds_fhdr.dwWidth, dds_fhdr.dwHeight, dds_fhdr.dwSize, dds_fhdr.dwLinearSize);
|
||||
|
||||
if (!(dds_fhdr.dwFlags & (DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT|DDSD_LINEARSIZE))) {
|
||||
DBG_INFO(80, L"Error: incompatible dds format!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((dds_fhdr.dwFlags & DDSD_MIPMAPCOUNT) && dds_fhdr.dwMipMapCount != 1) {
|
||||
DBG_INFO(80, L"Error: mipmapped dds not supported!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!((dds_fhdr.ddpf.dwFlags & DDPF_FOURCC) && dds_fhdr.dwCaps2 == 0)) {
|
||||
DBG_INFO(80, L"Error: not fourcc standard texture!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (memcmp(&dds_fhdr.ddpf.dwFourCC, "DXT1", 4) == 0) {
|
||||
DBG_INFO(80, L"DXT1 format\n");
|
||||
/* compensate for missing LinearSize */
|
||||
dds_fhdr.dwLinearSize = (dds_fhdr.dwWidth * dds_fhdr.dwHeight) >> 1;
|
||||
tmpformat = GR_TEXFMT_ARGB_CMP_DXT1;
|
||||
} else if (memcmp(&dds_fhdr.ddpf.dwFourCC, "DXT3", 4) == 0) {
|
||||
DBG_INFO(80, L"DXT3 format\n");
|
||||
dds_fhdr.dwLinearSize = dds_fhdr.dwWidth * dds_fhdr.dwHeight;
|
||||
tmpformat = GR_TEXFMT_ARGB_CMP_DXT3;
|
||||
} else if (memcmp(&dds_fhdr.ddpf.dwFourCC, "DXT5", 4) == 0) {
|
||||
DBG_INFO(80, L"DXT5 format\n");
|
||||
dds_fhdr.dwLinearSize = dds_fhdr.dwWidth * dds_fhdr.dwHeight;
|
||||
tmpformat = GR_TEXFMT_ARGB_CMP_DXT5;
|
||||
} else {
|
||||
DBG_INFO(80, L"Error: not DXT1 or DXT3 or DXT5 format!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* read in image */
|
||||
image = (uint8*)malloc(dds_fhdr.dwLinearSize);
|
||||
if (image) {
|
||||
*width = dds_fhdr.dwWidth;
|
||||
*height = dds_fhdr.dwHeight;
|
||||
*format = tmpformat;
|
||||
|
||||
fseek(fp, 128, SEEK_SET); /* size of header is 128 bytes */
|
||||
fread(image, dds_fhdr.dwLinearSize, 1, fp);
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Texture Filtering
|
||||
* Version: 1.0
|
||||
*
|
||||
* Copyright (C) 2007 Hiroshi Morii All Rights Reserved.
|
||||
* Email koolsmoky(at)users.sourceforge.net
|
||||
* Web http://www.3dfxzone.it/koolsmoky
|
||||
*
|
||||
* this 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* this 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __TXIMAGE_H__
|
||||
#define __TXIMAGE_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <png/png.h>
|
||||
#include "TxInternal.h"
|
||||
|
||||
#ifndef WIN32
|
||||
typedef struct tagBITMAPFILEHEADER {
|
||||
unsigned short bfType;
|
||||
unsigned long bfSize;
|
||||
unsigned short bfReserved1;
|
||||
unsigned short bfReserved2;
|
||||
unsigned long bfOffBits;
|
||||
} BITMAPFILEHEADER;
|
||||
|
||||
typedef struct tagBITMAPINFOHEADER {
|
||||
unsigned long biSize;
|
||||
long biWidth;
|
||||
long biHeight;
|
||||
unsigned short biPlanes;
|
||||
unsigned short biBitCount;
|
||||
unsigned long biCompression;
|
||||
unsigned long biSizeImage;
|
||||
long biXPelsPerMeter;
|
||||
long biYPelsPerMeter;
|
||||
unsigned long biClrUsed;
|
||||
unsigned long biClrImportant;
|
||||
} BITMAPINFOHEADER;
|
||||
#else
|
||||
typedef struct tagBITMAPFILEHEADER BITMAPFILEHEADER;
|
||||
typedef struct tagBITMAPINFOHEADER BITMAPINFOHEADER;
|
||||
#endif
|
||||
|
||||
#define DDSD_CAPS 0x00000001
|
||||
#define DDSD_HEIGHT 0x00000002
|
||||
#define DDSD_WIDTH 0x00000004
|
||||
#define DDSD_PITCH 0x00000008
|
||||
#define DDSD_PIXELFORMAT 0x00001000
|
||||
#define DDSD_MIPMAPCOUNT 0x00020000
|
||||
#define DDSD_LINEARSIZE 0x00080000
|
||||
#define DDSD_DEPTH 0x00800000
|
||||
|
||||
#define DDPF_ALPHAPIXELS 0x00000001
|
||||
#define DDPF_FOURCC 0x00000004
|
||||
#define DDPF_RGB 0x00000040
|
||||
|
||||
#define DDSCAPS_COMPLEX 0x00000008
|
||||
#define DDSCAPS_TEXTURE 0x00001000
|
||||
#define DDSCAPS_MIPMAP 0x00400000
|
||||
|
||||
typedef struct tagDDSPIXELFORMAT {
|
||||
unsigned long dwSize;
|
||||
unsigned long dwFlags;
|
||||
unsigned long dwFourCC;
|
||||
unsigned long dwRGBBitCount;
|
||||
unsigned long dwRBitMask;
|
||||
unsigned long dwGBitMask;
|
||||
unsigned long dwBBitMask;
|
||||
unsigned long dwRGBAlphaBitMask;
|
||||
} DDSPIXELFORMAT;
|
||||
|
||||
typedef struct tagDDSFILEHEADER {
|
||||
unsigned long dwMagic;
|
||||
unsigned long dwSize;
|
||||
unsigned long dwFlags;
|
||||
unsigned long dwHeight;
|
||||
unsigned long dwWidth;
|
||||
unsigned long dwLinearSize;
|
||||
unsigned long dwDepth;
|
||||
unsigned long dwMipMapCount;
|
||||
unsigned long dwReserved1[11];
|
||||
DDSPIXELFORMAT ddpf;
|
||||
unsigned long dwCaps1;
|
||||
unsigned long dwCaps2;
|
||||
} DDSFILEHEADER;
|
||||
|
||||
class TxImage
|
||||
{
|
||||
private:
|
||||
boolean getPNGInfo(FILE *fp, png_structp *png_ptr, png_infop *info_ptr);
|
||||
boolean getBMPInfo(FILE *fp, BITMAPFILEHEADER *bmp_fhdr, BITMAPINFOHEADER *bmp_ihdr);
|
||||
boolean getDDSInfo(FILE *fp, DDSFILEHEADER *dds_fhdr);
|
||||
public:
|
||||
TxImage() {}
|
||||
~TxImage() {}
|
||||
uint8* readPNG(FILE* fp, int* width, int* height, uint16* format);
|
||||
boolean writePNG(uint8* src, FILE* fp, int width, int height, int rowStride, uint16 format, uint8 *palette);
|
||||
uint8* readBMP(FILE* fp, int* width, int* height, uint16* format);
|
||||
uint8* readDDS(FILE* fp, int* width, int* height, uint16* format);
|
||||
};
|
||||
|
||||
#endif /* __TXIMAGE_H__ */
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Texture Filtering
|
||||
* Version: 1.0
|
||||
*
|
||||
* Copyright (C) 2007 Hiroshi Morii All Rights Reserved.
|
||||
* Email koolsmoky(at)users.sourceforge.net
|
||||
* Web http://www.3dfxzone.it/koolsmoky
|
||||
*
|
||||
* this 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* this 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __INTERNAL_H__
|
||||
#define __INTERNAL_H__
|
||||
|
||||
#include "Ext_TxFilter.h"
|
||||
|
||||
/* dll exports */
|
||||
#ifdef TXFILTER_DLL
|
||||
#define TAPI __declspec(dllexport)
|
||||
#define TAPIENTRY
|
||||
#else
|
||||
#define TAPI
|
||||
#define TAPIENTRY
|
||||
#endif
|
||||
|
||||
typedef unsigned char uint8;
|
||||
typedef unsigned short uint16;
|
||||
typedef unsigned long uint32;
|
||||
|
||||
#ifdef WIN32
|
||||
#define KBHIT(key) ((GetAsyncKeyState(key) & 0x8001) == 0x8001)
|
||||
#else
|
||||
#define KBHIT(key) (0)
|
||||
#endif
|
||||
|
||||
/* from OpenGL glext.h */
|
||||
#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
|
||||
#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
|
||||
#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
|
||||
#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
|
||||
|
||||
/* for explicit fxt1 compression */
|
||||
#define CC_CHROMA 0x0
|
||||
#define CC_HI 0x1
|
||||
#define CC_ALPHA 0x2
|
||||
|
||||
/* in-memory zlib texture compression */
|
||||
#define GR_TEXFMT_GZ 0x8000
|
||||
|
||||
#if 0 /* this is here to remind me of other formats */
|
||||
/* from 3Dfx Interactive Inc. glide.h */
|
||||
#define GR_TEXFMT_8BIT 0x0
|
||||
#define GR_TEXFMT_RGB_332 GR_TEXFMT_8BIT
|
||||
#define GR_TEXFMT_YIQ_422 0x1
|
||||
#define GR_TEXFMT_ALPHA_8 0x2 /* (0..0xFF) alpha */
|
||||
#define GR_TEXFMT_INTENSITY_8 0x3 /* (0..0xFF) intensity */
|
||||
#define GR_TEXFMT_ALPHA_INTENSITY_44 0x4
|
||||
#define GR_TEXFMT_P_8 0x5 /* 8-bit palette */
|
||||
#define GR_TEXFMT_RSVD0 0x6 /* GR_TEXFMT_P_8_RGBA */
|
||||
#define GR_TEXFMT_P_8_6666 GR_TEXFMT_RSVD0
|
||||
#define GR_TEXFMT_P_8_6666_EXT GR_TEXFMT_RSVD0
|
||||
#define GR_TEXFMT_RSVD1 0x7
|
||||
#define GR_TEXFMT_16BIT 0x8
|
||||
#define GR_TEXFMT_ARGB_8332 GR_TEXFMT_16BIT
|
||||
#define GR_TEXFMT_AYIQ_8422 0x9
|
||||
#define GR_TEXFMT_RGB_565 0xa
|
||||
#define GR_TEXFMT_ARGB_1555 0xb
|
||||
#define GR_TEXFMT_ARGB_4444 0xc
|
||||
#define GR_TEXFMT_ALPHA_INTENSITY_88 0xd
|
||||
#define GR_TEXFMT_AP_88 0xe /* 8-bit alpha 8-bit palette */
|
||||
#define GR_TEXFMT_RSVD2 0xf
|
||||
#define GR_TEXFMT_RSVD4 GR_TEXFMT_RSVD2
|
||||
|
||||
/* from 3Dfx Interactive Inc. g3ext.h */
|
||||
#define GR_TEXFMT_ARGB_CMP_FXT1 0x11
|
||||
#define GR_TEXFMT_ARGB_8888 0x12
|
||||
#define GR_TEXFMT_YUYV_422 0x13
|
||||
#define GR_TEXFMT_UYVY_422 0x14
|
||||
#define GR_TEXFMT_AYUV_444 0x15
|
||||
#define GR_TEXFMT_ARGB_CMP_DXT1 0x16
|
||||
#define GR_TEXFMT_ARGB_CMP_DXT2 0x17
|
||||
#define GR_TEXFMT_ARGB_CMP_DXT3 0x18
|
||||
#define GR_TEXFMT_ARGB_CMP_DXT4 0x19
|
||||
#define GR_TEXFMT_ARGB_CMP_DXT5 0x1A
|
||||
#define GR_TEXTFMT_RGB_888 0xFF
|
||||
#endif
|
||||
|
||||
#endif /* __INTERNAL_H__ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Texture Filtering
|
||||
* Version: 1.0
|
||||
*
|
||||
* Copyright (C) 2007 Hiroshi Morii All Rights Reserved.
|
||||
* Email koolsmoky(at)users.sourceforge.net
|
||||
* Web http://www.3dfxzone.it/koolsmoky
|
||||
*
|
||||
* this 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* this 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __TXQUANTIZE_H__
|
||||
#define __TXQUANTIZE_H__
|
||||
|
||||
/* Glide64 DXTn workaround
|
||||
* (0:disable, 1:enable) */
|
||||
#define GLIDE64_DXTN 1
|
||||
|
||||
#include "TxInternal.h"
|
||||
#include "TxUtil.h"
|
||||
|
||||
class TxQuantize
|
||||
{
|
||||
private:
|
||||
TxUtil *_txUtil;
|
||||
int _numcore;
|
||||
|
||||
fxtCompressTexFuncExt _tx_compress_fxt1;
|
||||
dxtCompressTexFuncExt _tx_compress_dxtn;
|
||||
|
||||
/* fast optimized... well, sort of. */
|
||||
void ARGB1555_ARGB8888(uint32* src, uint32* dst, int width, int height);
|
||||
void ARGB4444_ARGB8888(uint32* src, uint32* dst, int width, int height);
|
||||
void RGB565_ARGB8888(uint32* src, uint32* dst, int width, int height);
|
||||
void A8_ARGB8888(uint32* src, uint32* dst, int width, int height);
|
||||
void AI44_ARGB8888(uint32* src, uint32* dst, int width, int height);
|
||||
void AI88_ARGB8888(uint32* src, uint32* dst, int width, int height);
|
||||
|
||||
void ARGB8888_ARGB1555(uint32* src, uint32* dst, int width, int height);
|
||||
void ARGB8888_ARGB4444(uint32* src, uint32* dst, int width, int height);
|
||||
void ARGB8888_RGB565(uint32* src, uint32* dst, int width, int height);
|
||||
void ARGB8888_A8(uint32* src, uint32* dst, int width, int height);
|
||||
void ARGB8888_AI44(uint32* src, uint32* dst, int width, int height);
|
||||
void ARGB8888_AI88(uint32* src, uint32* dst, int width, int height);
|
||||
|
||||
/* quality */
|
||||
void ARGB8888_RGB565_ErrD(uint32* src, uint32* dst, int width, int height);
|
||||
void ARGB8888_ARGB1555_ErrD(uint32* src, uint32* dst, int width, int height);
|
||||
void ARGB8888_ARGB4444_ErrD(uint32* src, uint32* dst, int width, int height);
|
||||
void ARGB8888_AI44_ErrD(uint32* src, uint32* dst, int width, int height);
|
||||
void ARGB8888_AI88_Slow(uint32* src, uint32* dst, int width, int height);
|
||||
void ARGB8888_I8_Slow(uint32* src, uint32* dst, int width, int height);
|
||||
|
||||
/* compressors */
|
||||
boolean FXT1(uint8 *src, uint8 *dest,
|
||||
int srcwidth, int srcheight, uint16 srcformat,
|
||||
int *destwidth, int *destheight, uint16 *destformat);
|
||||
boolean DXTn(uint8 *src, uint8 *dest,
|
||||
int srcwidth, int srcheight, uint16 srcformat,
|
||||
int *destwidth, int *destheight, uint16 *destformat);
|
||||
|
||||
public:
|
||||
TxQuantize();
|
||||
~TxQuantize();
|
||||
|
||||
/* others */
|
||||
void P8_16BPP(uint32* src, uint32* dst, int width, int height, uint32* palette);
|
||||
|
||||
boolean quantize(uint8* src, uint8* dest, int width, int height, uint16 srcformat, uint16 destformat, boolean fastQuantizer = 1);
|
||||
|
||||
boolean compress(uint8 *src, uint8 *dest,
|
||||
int srcwidth, int srcheight, uint16 srcformat,
|
||||
int *destwidth, int *destheight, uint16 *destformat,
|
||||
int compressionType);
|
||||
|
||||
|
||||
#if 0 /* unused */
|
||||
void ARGB8888_I8(uint32* src, uint32* dst, int width, int height);
|
||||
void I8_ARGB8888(uint32* src, uint32* dst, int width, int height);
|
||||
|
||||
void ARGB1555_ABGR8888(uint32* src, uint32* dst, int width, int height);
|
||||
void ARGB4444_ABGR8888(uint32* src, uint32* dst, int width, int height);
|
||||
void ARGB8888_ABGR8888(uint32* src, uint32* dst, int width, int height);
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* __TXQUANTIZE_H__ */
|
|
@ -0,0 +1,417 @@
|
|||
/*
|
||||
* Texture Filtering
|
||||
* Version: 1.0
|
||||
*
|
||||
* Copyright (C) 2007 Hiroshi Morii All Rights Reserved.
|
||||
* Email koolsmoky(at)users.sourceforge.net
|
||||
* Web http://www.3dfxzone.it/koolsmoky
|
||||
*
|
||||
* this 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* this 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "TxReSample.h"
|
||||
#include "TxDbg.h"
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
int
|
||||
TxReSample::nextPow2(int num)
|
||||
{
|
||||
num = num - 1;
|
||||
num = num | (num >> 1);
|
||||
num = num | (num >> 2);
|
||||
num = num | (num >> 4);
|
||||
num = num | (num >> 8);
|
||||
num = num | (num >> 16);
|
||||
/*num = num | (num >> 32);*//* for 64bit architecture */
|
||||
num = num + 1;
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
boolean
|
||||
TxReSample::nextPow2(uint8** image, int* width, int* height, int bpp, boolean use_3dfx = 0)
|
||||
{
|
||||
/* NOTE: bpp must be one of the follwing: 8, 16, 24, 32 bits per pixel */
|
||||
|
||||
if (!*image || !*width || !*height || !bpp)
|
||||
return 0;
|
||||
|
||||
int row_bytes = ((*width * bpp) >> 3);
|
||||
int o_row_bytes = row_bytes;
|
||||
int o_width = *width;
|
||||
int n_width = *width;
|
||||
int o_height = *height;
|
||||
int n_height = *height;
|
||||
|
||||
/* HACKALERT: I have explicitly subtracted (n) from width/height to
|
||||
* adjust textures that have (n) pixel larger width/height than
|
||||
* power of 2 size. This is a dirty hack for textures that have
|
||||
* munged aspect ratio by (n) pixel to the original.
|
||||
*/
|
||||
if (n_width > 64) n_width -= 4;
|
||||
else if (n_width > 16) n_width -= 2;
|
||||
else if (n_width > 4) n_width -= 1;
|
||||
|
||||
if (n_height > 64) n_height -= 4;
|
||||
else if (n_height > 16) n_height -= 2;
|
||||
else if (n_height > 4) n_height -= 1;
|
||||
|
||||
n_width = nextPow2(n_width);
|
||||
n_height = nextPow2(n_height);
|
||||
row_bytes = (n_width * bpp) >> 3;
|
||||
|
||||
/* 3dfx Glide3 format, W:H aspect ratio range (8:1 - 1:8) */
|
||||
if (use_3dfx) {
|
||||
if (n_width > n_height) {
|
||||
if (n_width > (n_height << 3))
|
||||
n_height = n_width >> 3;
|
||||
} else {
|
||||
if (n_height > (n_width << 3)) {
|
||||
n_width = n_height >> 3;
|
||||
row_bytes = (n_width * bpp) >> 3;
|
||||
}
|
||||
}
|
||||
DBG_INFO(80, L"using 3dfx W:H aspect ratio range (8:1 - 1:8).\n");
|
||||
}
|
||||
|
||||
/* do we really need to do this ? */
|
||||
if (o_width == n_width && o_height == n_height)
|
||||
return 1; /* nope */
|
||||
|
||||
DBG_INFO(80, L"expand image to next power of 2 dimensions. %d x %d -> %d x %d\n",
|
||||
o_width, o_height, n_width, n_height);
|
||||
|
||||
if (o_width > n_width)
|
||||
o_width = n_width;
|
||||
|
||||
if (o_height > n_height)
|
||||
o_height = n_height;
|
||||
|
||||
/* allocate memory to read in image */
|
||||
uint8 *pow2image = (uint8*)malloc(row_bytes * n_height);
|
||||
|
||||
/* read in image */
|
||||
if (pow2image) {
|
||||
int i, j;
|
||||
uint8 *tmpimage = *image, *tmppow2image = pow2image;
|
||||
|
||||
for (i = 0; i < o_height; i++) {
|
||||
/* copy row */
|
||||
memcpy(tmppow2image, tmpimage, ((o_width * bpp) >> 3));
|
||||
|
||||
/* expand to pow2 size by replication */
|
||||
for(j = ((o_width * bpp) >> 3); j < row_bytes; j++)
|
||||
tmppow2image[j] = tmppow2image[j - (bpp >> 3)];
|
||||
|
||||
tmppow2image += row_bytes;
|
||||
tmpimage += o_row_bytes;
|
||||
}
|
||||
/* expand to pow2 size by replication */
|
||||
for (i = o_height; i < n_height; i++)
|
||||
memcpy(&pow2image[row_bytes * i], &pow2image[row_bytes * (i - 1)], row_bytes);
|
||||
|
||||
free(*image);
|
||||
|
||||
*image = pow2image;
|
||||
*height = n_height;
|
||||
*width = n_width;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Ken Turkowski
|
||||
* Filters for Common Resampling Tasks
|
||||
* Apple Computer 1990
|
||||
*/
|
||||
double
|
||||
TxReSample::tent(double x)
|
||||
{
|
||||
if (x < 0.0) x = -x;
|
||||
if (x < 1.0) return (1.0 - x);
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double
|
||||
TxReSample::gaussian(double x)
|
||||
{
|
||||
if (x < 0) x = -x;
|
||||
if (x < 2.0) return pow(2.0, -2.0 * x * x);
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double
|
||||
TxReSample::sinc(double x)
|
||||
{
|
||||
if (x == 0) return 1.0;
|
||||
x *= M_PI;
|
||||
return (sin(x) / x);
|
||||
}
|
||||
|
||||
double
|
||||
TxReSample::lanczos3(double x)
|
||||
{
|
||||
if (x < 0) x = -x;
|
||||
if (x < 3.0) return (sinc(x) * sinc(x/3.0));
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/* Don P. Mitchell and Arun N. Netravali
|
||||
* Reconstruction Filters in Computer Graphics
|
||||
* SIGGRAPH '88
|
||||
* Proceedings of the 15th annual conference on Computer
|
||||
* graphics and interactive techniques, pp221-228, 1988
|
||||
*/
|
||||
double
|
||||
TxReSample::mitchell(double x)
|
||||
{
|
||||
if (x < 0) x = -x;
|
||||
if (x < 2.0) {
|
||||
const double B = 1.0 / 3.0;
|
||||
const double C = 1.0 / 3.0;
|
||||
if (x < 1.0) {
|
||||
x = (((12.0 - 9.0 * B - 6.0 * C) * (x * x * x))
|
||||
+ ((-18.0 + 12.0 * B + 6.0 * C) * (x * x))
|
||||
+ (6.0 - 2.0 * B));
|
||||
} else {
|
||||
x = (((-1.0 * B - 6.0 * C) * (x * x * x))
|
||||
+ ((6.0 * B + 30.0 * C) * (x * x))
|
||||
+ ((-12.0 * B - 48.0 * C) * x)
|
||||
+ (8.0 * B + 24.0 * C));
|
||||
}
|
||||
return (x / 6.0);
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/* J. F. Kaiser and W. A. Reed
|
||||
* Data smoothing using low-pass digital filters
|
||||
* Rev. Sci. instrum. 48 (11), pp1447-1457, 1977
|
||||
*/
|
||||
double
|
||||
TxReSample::besselI0(double x)
|
||||
{
|
||||
/* zero-order modified bessel function of the first kind */
|
||||
const double eps_coeff = 1E-16; /* small enough */
|
||||
double xh, sum, pow, ds;
|
||||
xh = 0.5 * x;
|
||||
sum = 1.0;
|
||||
pow = 1.0;
|
||||
ds = 1.0;
|
||||
int k = 0;
|
||||
while (ds > sum * eps_coeff) {
|
||||
k++;
|
||||
pow *= (xh / k);
|
||||
ds = pow * pow;
|
||||
sum = sum + ds;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
double
|
||||
TxReSample::kaiser(double x)
|
||||
{
|
||||
const double alpha = 4.0;
|
||||
const double half_window = 5.0;
|
||||
const double ratio = x / half_window;
|
||||
return sinc(x) * besselI0(alpha * sqrt(1 - ratio * ratio)) / besselI0(alpha);
|
||||
}
|
||||
|
||||
boolean
|
||||
TxReSample::minify(uint8 **src, int *width, int *height, int ratio)
|
||||
{
|
||||
/* NOTE: src must be ARGB8888, ratio is the inverse representation */
|
||||
|
||||
#if 0
|
||||
if (!*src || ratio < 2) return 0;
|
||||
|
||||
/* Box filtering.
|
||||
* It would be nice to do Kaiser filtering.
|
||||
* N64 uses narrow strip textures which makes it hard to filter effectively.
|
||||
*/
|
||||
|
||||
int x, y, x2, y2, offset, numtexel;
|
||||
uint32 A, R, G, B, texel;
|
||||
|
||||
int tmpwidth = *width / ratio;
|
||||
int tmpheight = *height / ratio;
|
||||
|
||||
uint8 *tmptex = (uint8*)malloc((tmpwidth * tmpheight) << 2);
|
||||
|
||||
if (tmptex) {
|
||||
numtexel = ratio * ratio;
|
||||
for (y = 0; y < tmpheight; y++) {
|
||||
offset = ratio * y * *width;
|
||||
for (x = 0; x < tmpwidth; x++) {
|
||||
A = R = G = B = 0;
|
||||
for (y2 = 0; y2 < ratio; y2++) {
|
||||
for (x2 = 0; x2 < ratio; x2++) {
|
||||
texel = ((uint32*)*src)[offset + *width * y2 + x2];
|
||||
A += (texel >> 24);
|
||||
R += ((texel >> 16) & 0x000000ff);
|
||||
G += ((texel >> 8) & 0x000000ff);
|
||||
B += (texel & 0x000000ff);
|
||||
}
|
||||
}
|
||||
A = (A + ratio) / numtexel;
|
||||
R = (R + ratio) / numtexel;
|
||||
G = (G + ratio) / numtexel;
|
||||
B = (B + ratio) / numtexel;
|
||||
((uint32*)tmptex)[y * tmpwidth + x] = ((A << 24) | (R << 16) | (G << 8) | B);
|
||||
offset += ratio;
|
||||
}
|
||||
}
|
||||
free(*src);
|
||||
*src = tmptex;
|
||||
*width = tmpwidth;
|
||||
*height = tmpheight;
|
||||
|
||||
DBG_INFO(80, L"minification ratio:%d -> %d x %d\n", ratio, *width, *height);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
DBG_INFO(80, L"Error: failed minification!\n");
|
||||
|
||||
return 0;
|
||||
|
||||
#else
|
||||
|
||||
if (!*src || ratio < 2) return 0;
|
||||
|
||||
/* Image Resampling */
|
||||
|
||||
/* half width of filter window.
|
||||
* NOTE: must be 1.0 or larger.
|
||||
*
|
||||
* kaiser-bessel 5, lanczos3 3, mitchell 2, gaussian 1.5, tent 1
|
||||
*/
|
||||
double half_window = 5.0;
|
||||
|
||||
int x, y, x2, y2, z;
|
||||
double A, R, G, B;
|
||||
uint32 texel;
|
||||
|
||||
int tmpwidth = *width / ratio;
|
||||
int tmpheight = *height / ratio;
|
||||
|
||||
/* resampled destination */
|
||||
uint8 *tmptex = (uint8*)malloc((tmpwidth * tmpheight) << 2);
|
||||
if (!tmptex) return 0;
|
||||
|
||||
/* work buffer. single row */
|
||||
uint8 *workbuf = (uint8*)malloc(*width << 2);
|
||||
if (!workbuf) {
|
||||
free(tmptex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* prepare filter lookup table. only half width required for symetric filters. */
|
||||
double *weight = (double*)malloc((int)((half_window * ratio) * sizeof(double)));
|
||||
if (!weight) {
|
||||
free(tmptex);
|
||||
free(workbuf);
|
||||
return 0;
|
||||
}
|
||||
for (x = 0; x < half_window * ratio; x++) {
|
||||
//weight[x] = tent((double)x / ratio) / ratio;
|
||||
//weight[x] = gaussian((double)x / ratio) / ratio;
|
||||
//weight[x] = lanczos3((double)x / ratio) / ratio;
|
||||
//weight[x] = mitchell((double)x / ratio) / ratio;
|
||||
weight[x] = kaiser((double)x / ratio) / ratio;
|
||||
}
|
||||
|
||||
/* linear convolution */
|
||||
for (y = 0; y < tmpheight; y++) {
|
||||
for (x = 0; x < *width; x++) {
|
||||
texel = ((uint32*)*src)[y * ratio * *width + x];
|
||||
A = (double)(texel >> 24) * weight[0];
|
||||
R = (double)((texel >> 16) & 0xff) * weight[0];
|
||||
G = (double)((texel >> 8) & 0xff) * weight[0];
|
||||
B = (double)((texel ) & 0xff) * weight[0];
|
||||
for (y2 = 1; y2 < half_window * ratio; y2++) {
|
||||
z = y * ratio + y2;
|
||||
if (z >= *height) z = *height - 1;
|
||||
texel = ((uint32*)*src)[z * *width + x];
|
||||
A += (double)(texel >> 24) * weight[y2];
|
||||
R += (double)((texel >> 16) & 0xff) * weight[y2];
|
||||
G += (double)((texel >> 8) & 0xff) * weight[y2];
|
||||
B += (double)((texel ) & 0xff) * weight[y2];
|
||||
z = y * ratio - y2;
|
||||
if (z < 0) z = 0;
|
||||
texel = ((uint32*)*src)[z * *width + x];
|
||||
A += (double)(texel >> 24) * weight[y2];
|
||||
R += (double)((texel >> 16) & 0xff) * weight[y2];
|
||||
G += (double)((texel >> 8) & 0xff) * weight[y2];
|
||||
B += (double)((texel ) & 0xff) * weight[y2];
|
||||
}
|
||||
if (A < 0) A = 0; else if (A > 255) A = 255;
|
||||
if (R < 0) R = 0; else if (R > 255) R = 255;
|
||||
if (G < 0) G = 0; else if (G > 255) G = 255;
|
||||
if (B < 0) B = 0; else if (B > 255) B = 255;
|
||||
((uint32*)workbuf)[x] = (((uint32)A << 24) | ((uint32)R << 16) | ((uint32)G << 8) | (uint32)B);
|
||||
}
|
||||
for (x = 0; x < tmpwidth; x++) {
|
||||
texel = ((uint32*)workbuf)[x * ratio];
|
||||
A = (double)(texel >> 24) * weight[0];
|
||||
R = (double)((texel >> 16) & 0xff) * weight[0];
|
||||
G = (double)((texel >> 8) & 0xff) * weight[0];
|
||||
B = (double)((texel ) & 0xff) * weight[0];
|
||||
for (x2 = 1; x2 < half_window * ratio; x2++) {
|
||||
z = x * ratio + x2;
|
||||
if (z >= *width) z = *width - 1;
|
||||
texel = ((uint32*)workbuf)[z];
|
||||
A += (double)(texel >> 24) * weight[x2];
|
||||
R += (double)((texel >> 16) & 0xff) * weight[x2];
|
||||
G += (double)((texel >> 8) & 0xff) * weight[x2];
|
||||
B += (double)((texel ) & 0xff) * weight[x2];
|
||||
z = x * ratio - x2;
|
||||
if (z < 0) z = 0;
|
||||
texel = ((uint32*)workbuf)[z];
|
||||
A += (double)(texel >> 24) * weight[x2];
|
||||
R += (double)((texel >> 16) & 0xff) * weight[x2];
|
||||
G += (double)((texel >> 8) & 0xff) * weight[x2];
|
||||
B += (double)((texel ) & 0xff) * weight[x2];
|
||||
}
|
||||
if (A < 0) A = 0; else if (A > 255) A = 255;
|
||||
if (R < 0) R = 0; else if (R > 255) R = 255;
|
||||
if (G < 0) G = 0; else if (G > 255) G = 255;
|
||||
if (B < 0) B = 0; else if (B > 255) B = 255;
|
||||
((uint32*)tmptex)[y * tmpwidth + x] = (((uint32)A << 24) | ((uint32)R << 16) | ((uint32)G << 8) | (uint32)B);
|
||||
}
|
||||
}
|
||||
|
||||
free(*src);
|
||||
*src = tmptex;
|
||||
free(weight);
|
||||
free(workbuf);
|
||||
*width = tmpwidth;
|
||||
*height = tmpheight;
|
||||
|
||||
DBG_INFO(80, L"minification ratio:%d -> %d x %d\n", ratio, *width, *height);
|
||||
|
||||
return 1;
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Texture Filtering
|
||||
* Version: 1.0
|
||||
*
|
||||
* Copyright (C) 2007 Hiroshi Morii All Rights Reserved.
|
||||
* Email koolsmoky(at)users.sourceforge.net
|
||||
* Web http://www.3dfxzone.it/koolsmoky
|
||||
*
|
||||
* this 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* this 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __TXRESAMPLE_H__
|
||||
#define __TXRESAMPLE_H__
|
||||
|
||||
#include "TxInternal.h"
|
||||
|
||||
class TxReSample
|
||||
{
|
||||
private:
|
||||
double tent(double x);
|
||||
double gaussian(double x);
|
||||
double sinc(double x);
|
||||
double lanczos3(double x);
|
||||
double mitchell(double x);
|
||||
double besselI0(double x);
|
||||
double kaiser(double x);
|
||||
public:
|
||||
boolean minify(uint8 **src, int *width, int *height, int ratio);
|
||||
boolean nextPow2(uint8** image, int* width, int* height, int bpp, boolean use_3dfx);
|
||||
int nextPow2(int num);
|
||||
};
|
||||
|
||||
#endif /* __TXRESAMPLE_H__ */
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Texture Filtering
|
||||
* Version: 1.0
|
||||
*
|
||||
* Copyright (C) 2007 Hiroshi Morii All Rights Reserved.
|
||||
* Email koolsmoky(at)users.sourceforge.net
|
||||
* Web http://www.3dfxzone.it/koolsmoky
|
||||
*
|
||||
* this 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* this 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#pragma warning(disable: 4786)
|
||||
#endif
|
||||
|
||||
/* dump cache to disk (0:disable, 1:enable) */
|
||||
#define DUMP_CACHE 1
|
||||
|
||||
#include "TxTexCache.h"
|
||||
#include "TxDbg.h"
|
||||
#include <zlib/zlib.h>
|
||||
#include <string>
|
||||
#include <Common/path.h>
|
||||
|
||||
TxTexCache::~TxTexCache()
|
||||
{
|
||||
#if DUMP_CACHE
|
||||
if (_options & DUMP_TEXCACHE) {
|
||||
/* dump cache to disk */
|
||||
std::wstring filename = _ident + L"_MEMORYCACHE.dat";
|
||||
CPath cachepath(stdstr().FromUTF16(_path.c_str()).c_str(),"");
|
||||
cachepath.AppendDirectory("cache");
|
||||
|
||||
int config = _options & (FILTER_MASK|ENHANCEMENT_MASK|COMPRESS_TEX|COMPRESSION_MASK|FORCE16BPP_TEX|GZ_TEXCACHE);
|
||||
|
||||
TxCache::save(stdstr(cachepath).ToUTF16().c_str(), filename.c_str(), config);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
TxTexCache::TxTexCache(int options, int cachesize, const wchar_t *path, const wchar_t *ident,
|
||||
dispInfoFuncExt callback
|
||||
) : TxCache((options & ~GZ_HIRESTEXCACHE), cachesize, path, ident, callback)
|
||||
{
|
||||
/* assert local options */
|
||||
if (_path.empty() || _ident.empty() || !_cacheSize)
|
||||
_options &= ~DUMP_TEXCACHE;
|
||||
|
||||
#if DUMP_CACHE
|
||||
if (_options & DUMP_TEXCACHE) {
|
||||
/* find it on disk */
|
||||
std::wstring filename = _ident + L"_MEMORYCACHE.dat";
|
||||
CPath cachepath(stdstr().FromUTF16(_path.c_str()),"");
|
||||
cachepath.AppendDirectory("cache");
|
||||
int config = _options & (FILTER_MASK|ENHANCEMENT_MASK|COMPRESS_TEX|COMPRESSION_MASK|FORCE16BPP_TEX|GZ_TEXCACHE);
|
||||
|
||||
TxCache::load(stdstr(cachepath).ToUTF16().c_str(), filename.c_str(), config);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
boolean
|
||||
TxTexCache::add(uint64 checksum, GHQTexInfo *info)
|
||||
{
|
||||
if (_cacheSize <= 0) return 0;
|
||||
|
||||
return TxCache::add(checksum, info);
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Texture Filtering
|
||||
* Version: 1.0
|
||||
*
|
||||
* Copyright (C) 2007 Hiroshi Morii All Rights Reserved.
|
||||
* Email koolsmoky(at)users.sourceforge.net
|
||||
* Web http://www.3dfxzone.it/koolsmoky
|
||||
*
|
||||
* this 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* this 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __TXTEXCACHE_H__
|
||||
#define __TXTEXCACHE_H__
|
||||
|
||||
#include "TxCache.h"
|
||||
|
||||
class TxTexCache : public TxCache
|
||||
{
|
||||
public:
|
||||
~TxTexCache();
|
||||
TxTexCache(int options, int cachesize, const wchar_t *path, const wchar_t *ident,
|
||||
dispInfoFuncExt callback);
|
||||
boolean add(uint64 checksum, /* checksum hi:palette low:texture */
|
||||
GHQTexInfo *info);
|
||||
};
|
||||
|
||||
#endif /* __TXTEXCACHE_H__ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Texture Filtering
|
||||
* Version: 1.0
|
||||
*
|
||||
* Copyright (C) 2007 Hiroshi Morii All Rights Reserved.
|
||||
* Email koolsmoky(at)users.sourceforge.net
|
||||
* Web http://www.3dfxzone.it/koolsmoky
|
||||
*
|
||||
* this 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* this 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __TXUTIL_H__
|
||||
#define __TXUTIL_H__
|
||||
|
||||
/* maximum number of CPU cores allowed */
|
||||
#define MAX_NUMCORE 8
|
||||
|
||||
#include "TxInternal.h"
|
||||
#include <string>
|
||||
|
||||
#ifndef DXTN_DLL
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
void tx_compress_dxtn(int srccomps, int width, int height,
|
||||
const void *source, int destformat, void *dest,
|
||||
int destRowStride);
|
||||
|
||||
int fxt1_encode(int width, int height, int comps,
|
||||
const void *source, int srcRowStride,
|
||||
void *dest, int destRowStride);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* DXTN_DLL */
|
||||
|
||||
typedef void (*dxtCompressTexFuncExt)(int srccomps, int width,
|
||||
int height, const void *srcPixData,
|
||||
int destformat, void *dest,
|
||||
int dstRowStride);
|
||||
|
||||
typedef int (*fxtCompressTexFuncExt)(int width, int height, int comps,
|
||||
const void *source, int srcRowStride,
|
||||
void *dest, int destRowStride);
|
||||
|
||||
class TxLoadLib
|
||||
{
|
||||
private:
|
||||
#ifdef DXTN_DLL
|
||||
HMODULE _dxtnlib;
|
||||
#endif
|
||||
fxtCompressTexFuncExt _tx_compress_fxt1;
|
||||
dxtCompressTexFuncExt _tx_compress_dxtn;
|
||||
TxLoadLib();
|
||||
public:
|
||||
static TxLoadLib* getInstance() {
|
||||
static TxLoadLib txLoadLib;
|
||||
return &txLoadLib;
|
||||
}
|
||||
~TxLoadLib();
|
||||
fxtCompressTexFuncExt getfxtCompressTexFuncExt();
|
||||
dxtCompressTexFuncExt getdxtCompressTexFuncExt();
|
||||
};
|
||||
|
||||
class TxUtil
|
||||
{
|
||||
private:
|
||||
uint32 Adler32(const uint8* data, int Len, uint32 Adler);
|
||||
uint32 Adler32(const uint8* src, int width, int height, int size, int rowStride);
|
||||
uint32 RiceCRC32(const uint8* src, int width, int height, int size, int rowStride);
|
||||
boolean RiceCRC32_CI4(const uint8* src, int width, int height, int size, int rowStride,
|
||||
uint32* crc32, uint32* cimax);
|
||||
boolean RiceCRC32_CI8(const uint8* src, int width, int height, int size, int rowStride,
|
||||
uint32* crc32, uint32* cimax);
|
||||
int log2(int num);
|
||||
public:
|
||||
TxUtil() { }
|
||||
~TxUtil() { }
|
||||
int sizeofTx(int width, int height, uint16 format);
|
||||
uint32 checksumTx(uint8 *data, int width, int height, uint16 format);
|
||||
#if 0 /* unused */
|
||||
uint32 chkAlpha(uint32* src, int width, int height);
|
||||
#endif
|
||||
uint32 checksum(uint8 *src, int width, int height, int size, int rowStride);
|
||||
uint64 checksum64(uint8 *src, int width, int height, int size, int rowStride, uint8 *palette);
|
||||
int grLodLog2(int w, int h);
|
||||
int grAspectRatioLog2(int w, int h);
|
||||
int getNumberofProcessors();
|
||||
};
|
||||
|
||||
class TxMemBuf
|
||||
{
|
||||
private:
|
||||
uint8 *_tex[2];
|
||||
uint32 _size[2];
|
||||
TxMemBuf();
|
||||
public:
|
||||
static TxMemBuf* getInstance() {
|
||||
static TxMemBuf txMemBuf;
|
||||
return &txMemBuf;
|
||||
}
|
||||
~TxMemBuf();
|
||||
boolean init(int maxwidth, int maxheight);
|
||||
void shutdown(void);
|
||||
uint8 *get(unsigned int num);
|
||||
uint32 size_of(unsigned int num);
|
||||
};
|
||||
|
||||
#endif /* __TXUTIL_H__ */
|
|
@ -0,0 +1,884 @@
|
|||
/*
|
||||
* DXTn codec
|
||||
* Version: 1.1
|
||||
*
|
||||
* Copyright (C) 2004 Daniel Borca All Rights Reserved.
|
||||
*
|
||||
* this 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* this 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/* Copyright (C) 2007 Hiroshi Morii <koolsmoky(at)users.sourceforge.net>
|
||||
* Added support for ARGB inputs, DXT3,5 workaround for ATI Radeons, and
|
||||
* YUV conversions to determine representative colors.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "internal.h"
|
||||
#include "dxtn.h"
|
||||
|
||||
|
||||
/***************************************************************************\
|
||||
* DXTn encoder
|
||||
*
|
||||
* The encoder was built by reversing the decoder,
|
||||
* and is vaguely based on FXT1 codec. Note that this code
|
||||
* is merely a proof of concept, since it is highly UNoptimized!
|
||||
\***************************************************************************/
|
||||
|
||||
|
||||
#define MAX_COMP 4 /* ever needed maximum number of components in texel */
|
||||
#define MAX_VECT 4 /* ever needed maximum number of base vectors to find */
|
||||
#define N_TEXELS 16 /* number of texels in a block (always 16) */
|
||||
#define COLOR565(v) (word)((((v)[RCOMP] & 0xf8) << 8) | (((v)[GCOMP] & 0xfc) << 3) | ((v)[BCOMP] >> 3))
|
||||
|
||||
|
||||
static const int dxtn_color_tlat[2][4] = {
|
||||
{ 0, 2, 3, 1 },
|
||||
{ 0, 2, 1, 3 }
|
||||
};
|
||||
|
||||
static const int dxtn_alpha_tlat[2][8] = {
|
||||
{ 0, 2, 3, 4, 5, 6, 7, 1 },
|
||||
{ 0, 2, 3, 4, 5, 1, 6, 7 }
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
dxt1_rgb_quantize (dword *cc, const byte *lines[], int comps)
|
||||
{
|
||||
float b, iv[MAX_COMP]; /* interpolation vector */
|
||||
|
||||
dword hi; /* high doubleword */
|
||||
int color0, color1;
|
||||
int n_vect;
|
||||
const int n_comp = 3;
|
||||
int black = 0;
|
||||
|
||||
#ifndef YUV
|
||||
int minSum = 2000; /* big enough */
|
||||
#else
|
||||
int minSum = 2000000;
|
||||
#endif
|
||||
int maxSum = -1; /* small enough */
|
||||
int minCol = 0; /* phoudoin: silent compiler! */
|
||||
int maxCol = 0; /* phoudoin: silent compiler! */
|
||||
|
||||
byte input[N_TEXELS][MAX_COMP];
|
||||
int i, k, l;
|
||||
|
||||
/* make the whole block opaque */
|
||||
/* we will NEVER reference ACOMP of any pixel */
|
||||
|
||||
/* 4 texels each line */
|
||||
#ifndef ARGB
|
||||
for (l = 0; l < 4; l++) {
|
||||
for (k = 0; k < 4; k++) {
|
||||
for (i = 0; i < comps; i++) {
|
||||
input[k + l * 4][i] = *lines[l]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* H.Morii - support for ARGB inputs */
|
||||
for (l = 0; l < 4; l++) {
|
||||
for (k = 0; k < 4; k++) {
|
||||
input[k + l * 4][2] = *lines[l]++;
|
||||
input[k + l * 4][1] = *lines[l]++;
|
||||
input[k + l * 4][0] = *lines[l]++;
|
||||
if (comps == 4) input[k + l * 4][3] = *lines[l]++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Our solution here is to find the darkest and brightest colors in
|
||||
* the 4x4 tile and use those as the two representative colors.
|
||||
* There are probably better algorithms to use (histogram-based).
|
||||
*/
|
||||
for (k = 0; k < N_TEXELS; k++) {
|
||||
int sum = 0;
|
||||
#ifndef YUV
|
||||
for (i = 0; i < n_comp; i++) {
|
||||
sum += input[k][i];
|
||||
}
|
||||
#else
|
||||
/* RGB to YUV conversion according to CCIR 601 specs
|
||||
* Y = 0.299R+0.587G+0.114B
|
||||
* U = 0.713(R - Y) = 0.500R-0.419G-0.081B
|
||||
* V = 0.564(B - Y) = -0.169R-0.331G+0.500B
|
||||
*/
|
||||
sum = 299 * input[k][RCOMP] + 587 * input[k][GCOMP] + 114 * input[k][BCOMP];
|
||||
#endif
|
||||
if (minSum > sum) {
|
||||
minSum = sum;
|
||||
minCol = k;
|
||||
}
|
||||
if (maxSum < sum) {
|
||||
maxSum = sum;
|
||||
maxCol = k;
|
||||
}
|
||||
if (sum == 0) {
|
||||
black = 1;
|
||||
}
|
||||
}
|
||||
|
||||
color0 = COLOR565(input[minCol]);
|
||||
color1 = COLOR565(input[maxCol]);
|
||||
|
||||
if (color0 == color1) {
|
||||
/* we'll use 3-vector */
|
||||
cc[0] = color0 | (color1 << 16);
|
||||
hi = black ? -1 : 0;
|
||||
} else {
|
||||
if (black && ((color0 == 0) || (color1 == 0))) {
|
||||
/* we still can use 4-vector */
|
||||
black = 0;
|
||||
}
|
||||
|
||||
if (black ^ (color0 <= color1)) {
|
||||
int aux;
|
||||
aux = color0;
|
||||
color0 = color1;
|
||||
color1 = aux;
|
||||
aux = minCol;
|
||||
minCol = maxCol;
|
||||
maxCol = aux;
|
||||
}
|
||||
n_vect = (color0 <= color1) ? 2 : 3;
|
||||
|
||||
MAKEIVEC(n_vect, n_comp, iv, b, input[minCol], input[maxCol]);
|
||||
|
||||
/* add in texels */
|
||||
cc[0] = color0 | (color1 << 16);
|
||||
hi = 0;
|
||||
for (k = N_TEXELS - 1; k >= 0; k--) {
|
||||
int texel = 3;
|
||||
int sum = 0;
|
||||
if (black) {
|
||||
for (i = 0; i < n_comp; i++) {
|
||||
sum += input[k][i];
|
||||
}
|
||||
}
|
||||
if (!black || sum) {
|
||||
/* interpolate color */
|
||||
CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
|
||||
texel = dxtn_color_tlat[black][texel];
|
||||
}
|
||||
/* add in texel */
|
||||
hi <<= 2;
|
||||
hi |= texel;
|
||||
}
|
||||
}
|
||||
cc[1] = hi;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
dxt1_rgba_quantize (dword *cc, const byte *lines[], int comps)
|
||||
{
|
||||
float b, iv[MAX_COMP]; /* interpolation vector */
|
||||
|
||||
dword hi; /* high doubleword */
|
||||
int color0, color1;
|
||||
int n_vect;
|
||||
const int n_comp = 3;
|
||||
int transparent = 0;
|
||||
|
||||
#ifndef YUV
|
||||
int minSum = 2000; /* big enough */
|
||||
#else
|
||||
int minSum = 2000000;
|
||||
#endif
|
||||
int maxSum = -1; /* small enough */
|
||||
int minCol = 0; /* phoudoin: silent compiler! */
|
||||
int maxCol = 0; /* phoudoin: silent compiler! */
|
||||
|
||||
byte input[N_TEXELS][MAX_COMP];
|
||||
int i, k, l;
|
||||
|
||||
if (comps == 3) {
|
||||
/* make the whole block opaque */
|
||||
memset(input, -1, sizeof(input));
|
||||
}
|
||||
|
||||
/* 4 texels each line */
|
||||
#ifndef ARGB
|
||||
for (l = 0; l < 4; l++) {
|
||||
for (k = 0; k < 4; k++) {
|
||||
for (i = 0; i < comps; i++) {
|
||||
input[k + l * 4][i] = *lines[l]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* H.Morii - support for ARGB inputs */
|
||||
for (l = 0; l < 4; l++) {
|
||||
for (k = 0; k < 4; k++) {
|
||||
input[k + l * 4][2] = *lines[l]++;
|
||||
input[k + l * 4][1] = *lines[l]++;
|
||||
input[k + l * 4][0] = *lines[l]++;
|
||||
if (comps == 4) input[k + l * 4][3] = *lines[l]++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Our solution here is to find the darkest and brightest colors in
|
||||
* the 4x4 tile and use those as the two representative colors.
|
||||
* There are probably better algorithms to use (histogram-based).
|
||||
*/
|
||||
for (k = 0; k < N_TEXELS; k++) {
|
||||
int sum = 0;
|
||||
#ifndef YUV
|
||||
for (i = 0; i < n_comp; i++) {
|
||||
sum += input[k][i];
|
||||
}
|
||||
#else
|
||||
sum = 299 * input[k][RCOMP] + 587 * input[k][GCOMP] + 114 * input[k][BCOMP];
|
||||
#endif
|
||||
if (minSum > sum) {
|
||||
minSum = sum;
|
||||
minCol = k;
|
||||
}
|
||||
if (maxSum < sum) {
|
||||
maxSum = sum;
|
||||
maxCol = k;
|
||||
}
|
||||
if (input[k][ACOMP] < 128) {
|
||||
transparent = 1;
|
||||
}
|
||||
}
|
||||
|
||||
color0 = COLOR565(input[minCol]);
|
||||
color1 = COLOR565(input[maxCol]);
|
||||
|
||||
if (color0 == color1) {
|
||||
/* we'll use 3-vector */
|
||||
cc[0] = color0 | (color1 << 16);
|
||||
hi = transparent ? -1 : 0;
|
||||
} else {
|
||||
if (transparent ^ (color0 <= color1)) {
|
||||
int aux;
|
||||
aux = color0;
|
||||
color0 = color1;
|
||||
color1 = aux;
|
||||
aux = minCol;
|
||||
minCol = maxCol;
|
||||
maxCol = aux;
|
||||
}
|
||||
n_vect = (color0 <= color1) ? 2 : 3;
|
||||
|
||||
MAKEIVEC(n_vect, n_comp, iv, b, input[minCol], input[maxCol]);
|
||||
|
||||
/* add in texels */
|
||||
cc[0] = color0 | (color1 << 16);
|
||||
hi = 0;
|
||||
for (k = N_TEXELS - 1; k >= 0; k--) {
|
||||
int texel = 3;
|
||||
if (input[k][ACOMP] >= 128) {
|
||||
/* interpolate color */
|
||||
CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
|
||||
texel = dxtn_color_tlat[transparent][texel];
|
||||
}
|
||||
/* add in texel */
|
||||
hi <<= 2;
|
||||
hi |= texel;
|
||||
}
|
||||
}
|
||||
cc[1] = hi;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
dxt3_rgba_quantize (dword *cc, const byte *lines[], int comps)
|
||||
{
|
||||
float b, iv[MAX_COMP]; /* interpolation vector */
|
||||
|
||||
dword lolo, lohi; /* low quadword: lo dword, hi dword */
|
||||
dword hihi; /* high quadword: high dword */
|
||||
int color0, color1;
|
||||
const int n_vect = 3;
|
||||
const int n_comp = 3;
|
||||
|
||||
#ifndef YUV
|
||||
int minSum = 2000; /* big enough */
|
||||
#else
|
||||
int minSum = 2000000;
|
||||
#endif
|
||||
int maxSum = -1; /* small enough */
|
||||
int minCol = 0; /* phoudoin: silent compiler! */
|
||||
int maxCol = 0; /* phoudoin: silent compiler! */
|
||||
|
||||
byte input[N_TEXELS][MAX_COMP];
|
||||
int i, k, l;
|
||||
|
||||
if (comps == 3) {
|
||||
/* make the whole block opaque */
|
||||
memset(input, -1, sizeof(input));
|
||||
}
|
||||
|
||||
/* 4 texels each line */
|
||||
#ifndef ARGB
|
||||
for (l = 0; l < 4; l++) {
|
||||
for (k = 0; k < 4; k++) {
|
||||
for (i = 0; i < comps; i++) {
|
||||
input[k + l * 4][i] = *lines[l]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* H.Morii - support for ARGB inputs */
|
||||
for (l = 0; l < 4; l++) {
|
||||
for (k = 0; k < 4; k++) {
|
||||
input[k + l * 4][2] = *lines[l]++;
|
||||
input[k + l * 4][1] = *lines[l]++;
|
||||
input[k + l * 4][0] = *lines[l]++;
|
||||
if (comps == 4) input[k + l * 4][3] = *lines[l]++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Our solution here is to find the darkest and brightest colors in
|
||||
* the 4x4 tile and use those as the two representative colors.
|
||||
* There are probably better algorithms to use (histogram-based).
|
||||
*/
|
||||
for (k = 0; k < N_TEXELS; k++) {
|
||||
int sum = 0;
|
||||
#ifndef YUV
|
||||
for (i = 0; i < n_comp; i++) {
|
||||
sum += input[k][i];
|
||||
}
|
||||
#else
|
||||
sum = 299 * input[k][RCOMP] + 587 * input[k][GCOMP] + 114 * input[k][BCOMP];
|
||||
#endif
|
||||
if (minSum > sum) {
|
||||
minSum = sum;
|
||||
minCol = k;
|
||||
}
|
||||
if (maxSum < sum) {
|
||||
maxSum = sum;
|
||||
maxCol = k;
|
||||
}
|
||||
}
|
||||
|
||||
/* add in alphas */
|
||||
lolo = lohi = 0;
|
||||
for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) {
|
||||
/* add in alpha */
|
||||
lohi <<= 4;
|
||||
lohi |= input[k][ACOMP] >> 4;
|
||||
}
|
||||
cc[1] = lohi;
|
||||
for (; k >= 0; k--) {
|
||||
/* add in alpha */
|
||||
lolo <<= 4;
|
||||
lolo |= input[k][ACOMP] >> 4;
|
||||
}
|
||||
cc[0] = lolo;
|
||||
|
||||
color0 = COLOR565(input[minCol]);
|
||||
color1 = COLOR565(input[maxCol]);
|
||||
|
||||
#ifdef RADEON
|
||||
/* H.Morii - Workaround for ATI Radeon
|
||||
* According to the OpenGL EXT_texture_compression_s3tc specs,
|
||||
* the encoding of the RGB components for DXT3 and DXT5 formats
|
||||
* use the non-transparent encodings of DXT1 but treated as
|
||||
* though color0 > color1, regardless of the actual values of
|
||||
* color0 and color1. ATI Radeons however require the values to
|
||||
* be color0 > color1.
|
||||
*/
|
||||
if (color0 < color1) {
|
||||
int aux;
|
||||
aux = color0;
|
||||
color0 = color1;
|
||||
color1 = aux;
|
||||
aux = minCol;
|
||||
minCol = maxCol;
|
||||
maxCol = aux;
|
||||
}
|
||||
#endif
|
||||
|
||||
cc[2] = color0 | (color1 << 16);
|
||||
|
||||
hihi = 0;
|
||||
if (color0 != color1) {
|
||||
MAKEIVEC(n_vect, n_comp, iv, b, input[minCol], input[maxCol]);
|
||||
|
||||
/* add in texels */
|
||||
for (k = N_TEXELS - 1; k >= 0; k--) {
|
||||
int texel;
|
||||
/* interpolate color */
|
||||
CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
|
||||
texel = dxtn_color_tlat[0][texel];
|
||||
/* add in texel */
|
||||
hihi <<= 2;
|
||||
hihi |= texel;
|
||||
}
|
||||
}
|
||||
cc[3] = hihi;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
dxt5_rgba_quantize (dword *cc, const byte *lines[], int comps)
|
||||
{
|
||||
float b, iv[MAX_COMP]; /* interpolation vector */
|
||||
|
||||
qword lo; /* low quadword */
|
||||
dword hihi; /* high quadword: high dword */
|
||||
int color0, color1;
|
||||
const int n_vect = 3;
|
||||
const int n_comp = 3;
|
||||
|
||||
#ifndef YUV
|
||||
int minSum = 2000; /* big enough */
|
||||
#else
|
||||
int minSum = 2000000;
|
||||
#endif
|
||||
int maxSum = -1; /* small enough */
|
||||
int minCol = 0; /* phoudoin: silent compiler! */
|
||||
int maxCol = 0; /* phoudoin: silent compiler! */
|
||||
int alpha0 = 2000; /* big enough */
|
||||
int alpha1 = -1; /* small enough */
|
||||
int anyZero = 0, anyOne = 0;
|
||||
int a_vect;
|
||||
|
||||
byte input[N_TEXELS][MAX_COMP];
|
||||
int i, k, l;
|
||||
|
||||
if (comps == 3) {
|
||||
/* make the whole block opaque */
|
||||
memset(input, -1, sizeof(input));
|
||||
}
|
||||
|
||||
/* 4 texels each line */
|
||||
#ifndef ARGB
|
||||
for (l = 0; l < 4; l++) {
|
||||
for (k = 0; k < 4; k++) {
|
||||
for (i = 0; i < comps; i++) {
|
||||
input[k + l * 4][i] = *lines[l]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* H.Morii - support for ARGB inputs */
|
||||
for (l = 0; l < 4; l++) {
|
||||
for (k = 0; k < 4; k++) {
|
||||
input[k + l * 4][2] = *lines[l]++;
|
||||
input[k + l * 4][1] = *lines[l]++;
|
||||
input[k + l * 4][0] = *lines[l]++;
|
||||
if (comps == 4) input[k + l * 4][3] = *lines[l]++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Our solution here is to find the darkest and brightest colors in
|
||||
* the 4x4 tile and use those as the two representative colors.
|
||||
* There are probably better algorithms to use (histogram-based).
|
||||
*/
|
||||
for (k = 0; k < N_TEXELS; k++) {
|
||||
int sum = 0;
|
||||
#ifndef YUV
|
||||
for (i = 0; i < n_comp; i++) {
|
||||
sum += input[k][i];
|
||||
}
|
||||
#else
|
||||
sum = 299 * input[k][RCOMP] + 587 * input[k][GCOMP] + 114 * input[k][BCOMP];
|
||||
#endif
|
||||
if (minSum > sum) {
|
||||
minSum = sum;
|
||||
minCol = k;
|
||||
}
|
||||
if (maxSum < sum) {
|
||||
maxSum = sum;
|
||||
maxCol = k;
|
||||
}
|
||||
if (alpha0 > input[k][ACOMP]) {
|
||||
alpha0 = input[k][ACOMP];
|
||||
}
|
||||
if (alpha1 < input[k][ACOMP]) {
|
||||
alpha1 = input[k][ACOMP];
|
||||
}
|
||||
if (input[k][ACOMP] == 0) {
|
||||
anyZero = 1;
|
||||
}
|
||||
if (input[k][ACOMP] == 255) {
|
||||
anyOne = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* add in alphas */
|
||||
if (alpha0 == alpha1) {
|
||||
/* we'll use 6-vector */
|
||||
cc[0] = alpha0 | (alpha1 << 8);
|
||||
cc[1] = 0;
|
||||
} else {
|
||||
if (anyZero && ((alpha0 == 0) || (alpha1 == 0))) {
|
||||
/* we still might use 8-vector */
|
||||
anyZero = 0;
|
||||
}
|
||||
if (anyOne && ((alpha0 == 255) || (alpha1 == 255))) {
|
||||
/* we still might use 8-vector */
|
||||
anyOne = 0;
|
||||
}
|
||||
if ((anyZero | anyOne) ^ (alpha0 <= alpha1)) {
|
||||
int aux;
|
||||
aux = alpha0;
|
||||
alpha0 = alpha1;
|
||||
alpha1 = aux;
|
||||
}
|
||||
a_vect = (alpha0 <= alpha1) ? 5 : 7;
|
||||
|
||||
/* compute interpolation vector */
|
||||
iv[ACOMP] = (float)a_vect / (alpha1 - alpha0);
|
||||
b = -iv[ACOMP] * alpha0 + 0.5F;
|
||||
|
||||
/* add in alphas */
|
||||
Q_MOV32(lo, 0);
|
||||
for (k = N_TEXELS - 1; k >= 0; k--) {
|
||||
int texel = -1;
|
||||
if (anyZero | anyOne) {
|
||||
if (input[k][ACOMP] == 0) {
|
||||
texel = 6;
|
||||
} else if (input[k][ACOMP] == 255) {
|
||||
texel = 7;
|
||||
}
|
||||
}
|
||||
/* interpolate alpha */
|
||||
if (texel == -1) {
|
||||
float dot = input[k][ACOMP] * iv[ACOMP];
|
||||
texel = (int)(dot + b);
|
||||
#if SAFECDOT
|
||||
if (texel < 0) {
|
||||
texel = 0;
|
||||
} else if (texel > a_vect) {
|
||||
texel = a_vect;
|
||||
}
|
||||
#endif
|
||||
texel = dxtn_alpha_tlat[anyZero | anyOne][texel];
|
||||
}
|
||||
/* add in texel */
|
||||
Q_SHL(lo, 3);
|
||||
Q_OR32(lo, texel);
|
||||
}
|
||||
Q_SHL(lo, 16);
|
||||
Q_OR32(lo, alpha0 | (alpha1 << 8));
|
||||
((qword *)cc)[0] = lo;
|
||||
}
|
||||
|
||||
color0 = COLOR565(input[minCol]);
|
||||
color1 = COLOR565(input[maxCol]);
|
||||
|
||||
#ifdef RADEON /* H.Morii - Workaround for ATI Radeon */
|
||||
if (color0 < color1) {
|
||||
int aux;
|
||||
aux = color0;
|
||||
color0 = color1;
|
||||
color1 = aux;
|
||||
aux = minCol;
|
||||
minCol = maxCol;
|
||||
maxCol = aux;
|
||||
}
|
||||
#endif
|
||||
|
||||
cc[2] = color0 | (color1 << 16);
|
||||
|
||||
hihi = 0;
|
||||
if (color0 != color1) {
|
||||
MAKEIVEC(n_vect, n_comp, iv, b, input[minCol], input[maxCol]);
|
||||
|
||||
/* add in texels */
|
||||
for (k = N_TEXELS - 1; k >= 0; k--) {
|
||||
int texel;
|
||||
/* interpolate color */
|
||||
CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
|
||||
texel = dxtn_color_tlat[0][texel];
|
||||
/* add in texel */
|
||||
hihi <<= 2;
|
||||
hihi |= texel;
|
||||
}
|
||||
}
|
||||
cc[3] = hihi;
|
||||
}
|
||||
|
||||
|
||||
#define ENCODER(dxtn, n) \
|
||||
int TAPIENTRY \
|
||||
dxtn##_encode (int width, int height, int comps, \
|
||||
const void *source, int srcRowStride, \
|
||||
void *dest, int destRowStride) \
|
||||
{ \
|
||||
int x, y; \
|
||||
const byte *data; \
|
||||
dword *encoded = (dword *)dest; \
|
||||
void *newSource = NULL; \
|
||||
\
|
||||
/* Replicate image if width is not M4 or height is not M4 */ \
|
||||
if ((width & 3) | (height & 3)) { \
|
||||
int newWidth = (width + 3) & ~3; \
|
||||
int newHeight = (height + 3) & ~3; \
|
||||
newSource = malloc(comps * newWidth * newHeight * sizeof(byte *));\
|
||||
_mesa_upscale_teximage2d(width, height, newWidth, newHeight, \
|
||||
comps, (const byte *)source, \
|
||||
srcRowStride, (byte *)newSource); \
|
||||
source = newSource; \
|
||||
width = newWidth; \
|
||||
height = newHeight; \
|
||||
srcRowStride = comps * newWidth; \
|
||||
} \
|
||||
\
|
||||
data = (const byte *)source; \
|
||||
destRowStride = (destRowStride - width * n) / 4; \
|
||||
for (y = 0; y < height; y += 4) { \
|
||||
unsigned int offs = 0 + (y + 0) * srcRowStride; \
|
||||
for (x = 0; x < width; x += 4) { \
|
||||
const byte *lines[4]; \
|
||||
lines[0] = &data[offs]; \
|
||||
lines[1] = lines[0] + srcRowStride; \
|
||||
lines[2] = lines[1] + srcRowStride; \
|
||||
lines[3] = lines[2] + srcRowStride; \
|
||||
offs += 4 * comps; \
|
||||
dxtn##_quantize(encoded, lines, comps); \
|
||||
/* 4x4 block */ \
|
||||
encoded += n; \
|
||||
} \
|
||||
encoded += destRowStride; \
|
||||
} \
|
||||
\
|
||||
if (newSource != NULL) { \
|
||||
free(newSource); \
|
||||
} \
|
||||
\
|
||||
return 0; \
|
||||
}
|
||||
|
||||
ENCODER(dxt1_rgb, 2)
|
||||
ENCODER(dxt1_rgba, 2)
|
||||
ENCODER(dxt3_rgba, 4)
|
||||
ENCODER(dxt5_rgba, 4)
|
||||
|
||||
|
||||
/***************************************************************************\
|
||||
* DXTn decoder
|
||||
*
|
||||
* The decoder is based on GL_EXT_texture_compression_s3tc
|
||||
* specification and serves as a concept for the encoder.
|
||||
\***************************************************************************/
|
||||
|
||||
|
||||
/* lookup table for scaling 4 bit colors up to 8 bits */
|
||||
static const byte _rgb_scale_4[] = {
|
||||
0, 17, 34, 51, 68, 85, 102, 119,
|
||||
136, 153, 170, 187, 204, 221, 238, 255
|
||||
};
|
||||
|
||||
/* lookup table for scaling 5 bit colors up to 8 bits */
|
||||
static const byte _rgb_scale_5[] = {
|
||||
0, 8, 16, 25, 33, 41, 49, 58,
|
||||
66, 74, 82, 90, 99, 107, 115, 123,
|
||||
132, 140, 148, 156, 165, 173, 181, 189,
|
||||
197, 206, 214, 222, 230, 239, 247, 255
|
||||
};
|
||||
|
||||
/* lookup table for scaling 6 bit colors up to 8 bits */
|
||||
static const byte _rgb_scale_6[] = {
|
||||
0, 4, 8, 12, 16, 20, 24, 28,
|
||||
32, 36, 40, 45, 49, 53, 57, 61,
|
||||
65, 69, 73, 77, 81, 85, 89, 93,
|
||||
97, 101, 105, 109, 113, 117, 121, 125,
|
||||
130, 134, 138, 142, 146, 150, 154, 158,
|
||||
162, 166, 170, 174, 178, 182, 186, 190,
|
||||
194, 198, 202, 206, 210, 215, 219, 223,
|
||||
227, 231, 235, 239, 243, 247, 251, 255
|
||||
};
|
||||
|
||||
|
||||
#define CC_SEL(cc, which) (((dword *)(cc))[(which) / 32] >> ((which) & 31))
|
||||
#define UP4(c) _rgb_scale_4[(c) & 15]
|
||||
#define UP5(c) _rgb_scale_5[(c) & 31]
|
||||
#define UP6(c) _rgb_scale_6[(c) & 63]
|
||||
#define ZERO_4UBV(v) *((dword *)(v)) = 0
|
||||
|
||||
|
||||
void TAPIENTRY
|
||||
dxt1_rgb_decode_1 (const void *texture, int stride,
|
||||
int i, int j, byte *rgba)
|
||||
{
|
||||
const byte *src = (const byte *)texture
|
||||
+ ((j / 4) * ((stride + 3) / 4) + i / 4) * 8;
|
||||
const int code = (src[4 + (j & 3)] >> ((i & 3) * 2)) & 0x3;
|
||||
if (code == 0) {
|
||||
rgba[RCOMP] = UP5(CC_SEL(src, 11));
|
||||
rgba[GCOMP] = UP6(CC_SEL(src, 5));
|
||||
rgba[BCOMP] = UP5(CC_SEL(src, 0));
|
||||
} else if (code == 1) {
|
||||
rgba[RCOMP] = UP5(CC_SEL(src, 27));
|
||||
rgba[GCOMP] = UP6(CC_SEL(src, 21));
|
||||
rgba[BCOMP] = UP5(CC_SEL(src, 16));
|
||||
} else {
|
||||
const word col0 = src[0] | (src[1] << 8);
|
||||
const word col1 = src[2] | (src[3] << 8);
|
||||
if (col0 > col1) {
|
||||
if (code == 2) {
|
||||
rgba[RCOMP] = (UP5(col0 >> 11) * 2 + UP5(col1 >> 11)) / 3;
|
||||
rgba[GCOMP] = (UP6(col0 >> 5) * 2 + UP6(col1 >> 5)) / 3;
|
||||
rgba[BCOMP] = (UP5(col0 ) * 2 + UP5(col1 )) / 3;
|
||||
} else {
|
||||
rgba[RCOMP] = (UP5(col0 >> 11) + 2 * UP5(col1 >> 11)) / 3;
|
||||
rgba[GCOMP] = (UP6(col0 >> 5) + 2 * UP6(col1 >> 5)) / 3;
|
||||
rgba[BCOMP] = (UP5(col0 ) + 2 * UP5(col1 )) / 3;
|
||||
}
|
||||
} else {
|
||||
if (code == 2) {
|
||||
rgba[RCOMP] = (UP5(col0 >> 11) + UP5(col1 >> 11)) / 2;
|
||||
rgba[GCOMP] = (UP6(col0 >> 5) + UP6(col1 >> 5)) / 2;
|
||||
rgba[BCOMP] = (UP5(col0 ) + UP5(col1 )) / 2;
|
||||
} else {
|
||||
ZERO_4UBV(rgba);
|
||||
}
|
||||
}
|
||||
}
|
||||
rgba[ACOMP] = 255;
|
||||
}
|
||||
|
||||
|
||||
void TAPIENTRY
|
||||
dxt1_rgba_decode_1 (const void *texture, int stride,
|
||||
int i, int j, byte *rgba)
|
||||
{
|
||||
/* Same as rgb_dxt1 above, except alpha=0 if col0<=col1 and code=3. */
|
||||
const byte *src = (const byte *)texture
|
||||
+ ((j / 4) * ((stride + 3) / 4) + i / 4) * 8;
|
||||
const int code = (src[4 + (j & 3)] >> ((i & 3) * 2)) & 0x3;
|
||||
if (code == 0) {
|
||||
rgba[RCOMP] = UP5(CC_SEL(src, 11));
|
||||
rgba[GCOMP] = UP6(CC_SEL(src, 5));
|
||||
rgba[BCOMP] = UP5(CC_SEL(src, 0));
|
||||
rgba[ACOMP] = 255;
|
||||
} else if (code == 1) {
|
||||
rgba[RCOMP] = UP5(CC_SEL(src, 27));
|
||||
rgba[GCOMP] = UP6(CC_SEL(src, 21));
|
||||
rgba[BCOMP] = UP5(CC_SEL(src, 16));
|
||||
rgba[ACOMP] = 255;
|
||||
} else {
|
||||
const word col0 = src[0] | (src[1] << 8);
|
||||
const word col1 = src[2] | (src[3] << 8);
|
||||
if (col0 > col1) {
|
||||
if (code == 2) {
|
||||
rgba[RCOMP] = (UP5(col0 >> 11) * 2 + UP5(col1 >> 11)) / 3;
|
||||
rgba[GCOMP] = (UP6(col0 >> 5) * 2 + UP6(col1 >> 5)) / 3;
|
||||
rgba[BCOMP] = (UP5(col0 ) * 2 + UP5(col1 )) / 3;
|
||||
} else {
|
||||
rgba[RCOMP] = (UP5(col0 >> 11) + 2 * UP5(col1 >> 11)) / 3;
|
||||
rgba[GCOMP] = (UP6(col0 >> 5) + 2 * UP6(col1 >> 5)) / 3;
|
||||
rgba[BCOMP] = (UP5(col0 ) + 2 * UP5(col1 )) / 3;
|
||||
}
|
||||
rgba[ACOMP] = 255;
|
||||
} else {
|
||||
if (code == 2) {
|
||||
rgba[RCOMP] = (UP5(col0 >> 11) + UP5(col1 >> 11)) / 2;
|
||||
rgba[GCOMP] = (UP6(col0 >> 5) + UP6(col1 >> 5)) / 2;
|
||||
rgba[BCOMP] = (UP5(col0 ) + UP5(col1 )) / 2;
|
||||
rgba[ACOMP] = 255;
|
||||
} else {
|
||||
ZERO_4UBV(rgba);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TAPIENTRY
|
||||
dxt3_rgba_decode_1 (const void *texture, int stride,
|
||||
int i, int j, byte *rgba)
|
||||
{
|
||||
const byte *src = (const byte *)texture
|
||||
+ ((j / 4) * ((stride + 3) / 4) + i / 4) * 16;
|
||||
const int code = (src[12 + (j & 3)] >> ((i & 3) * 2)) & 0x3;
|
||||
const dword *cc = (const dword *)(src + 8);
|
||||
if (code == 0) {
|
||||
rgba[RCOMP] = UP5(CC_SEL(cc, 11));
|
||||
rgba[GCOMP] = UP6(CC_SEL(cc, 5));
|
||||
rgba[BCOMP] = UP5(CC_SEL(cc, 0));
|
||||
} else if (code == 1) {
|
||||
rgba[RCOMP] = UP5(CC_SEL(cc, 27));
|
||||
rgba[GCOMP] = UP6(CC_SEL(cc, 21));
|
||||
rgba[BCOMP] = UP5(CC_SEL(cc, 16));
|
||||
} else if (code == 2) {
|
||||
/* (col0 * (4 - code) + col1 * (code - 1)) / 3 */
|
||||
rgba[RCOMP] = (UP5(CC_SEL(cc, 11)) * 2 + UP5(CC_SEL(cc, 27))) / 3;
|
||||
rgba[GCOMP] = (UP6(CC_SEL(cc, 5)) * 2 + UP6(CC_SEL(cc, 21))) / 3;
|
||||
rgba[BCOMP] = (UP5(CC_SEL(cc, 0)) * 2 + UP5(CC_SEL(cc, 16))) / 3;
|
||||
} else {
|
||||
rgba[RCOMP] = (UP5(CC_SEL(cc, 11)) + 2 * UP5(CC_SEL(cc, 27))) / 3;
|
||||
rgba[GCOMP] = (UP6(CC_SEL(cc, 5)) + 2 * UP6(CC_SEL(cc, 21))) / 3;
|
||||
rgba[BCOMP] = (UP5(CC_SEL(cc, 0)) + 2 * UP5(CC_SEL(cc, 16))) / 3;
|
||||
}
|
||||
rgba[ACOMP] = UP4(src[((j & 3) * 4 + (i & 3)) / 2] >> ((i & 1) * 4));
|
||||
}
|
||||
|
||||
|
||||
void TAPIENTRY
|
||||
dxt5_rgba_decode_1 (const void *texture, int stride,
|
||||
int i, int j, byte *rgba)
|
||||
{
|
||||
const byte *src = (const byte *)texture
|
||||
+ ((j / 4) * ((stride + 3) / 4) + i / 4) * 16;
|
||||
const int code = (src[12 + (j & 3)] >> ((i & 3) * 2)) & 0x3;
|
||||
const dword *cc = (const dword *)(src + 8);
|
||||
const byte alpha0 = src[0];
|
||||
const byte alpha1 = src[1];
|
||||
const int alphaShift = (((j & 3) * 4) + (i & 3)) * 3 + 16;
|
||||
const int acode = ((alphaShift == 31)
|
||||
? CC_SEL(src + 2, alphaShift - 16)
|
||||
: CC_SEL(src, alphaShift)) & 0x7;
|
||||
if (code == 0) {
|
||||
rgba[RCOMP] = UP5(CC_SEL(cc, 11));
|
||||
rgba[GCOMP] = UP6(CC_SEL(cc, 5));
|
||||
rgba[BCOMP] = UP5(CC_SEL(cc, 0));
|
||||
} else if (code == 1) {
|
||||
rgba[RCOMP] = UP5(CC_SEL(cc, 27));
|
||||
rgba[GCOMP] = UP6(CC_SEL(cc, 21));
|
||||
rgba[BCOMP] = UP5(CC_SEL(cc, 16));
|
||||
} else if (code == 2) {
|
||||
/* (col0 * (4 - code) + col1 * (code - 1)) / 3 */
|
||||
rgba[RCOMP] = (UP5(CC_SEL(cc, 11)) * 2 + UP5(CC_SEL(cc, 27))) / 3;
|
||||
rgba[GCOMP] = (UP6(CC_SEL(cc, 5)) * 2 + UP6(CC_SEL(cc, 21))) / 3;
|
||||
rgba[BCOMP] = (UP5(CC_SEL(cc, 0)) * 2 + UP5(CC_SEL(cc, 16))) / 3;
|
||||
} else {
|
||||
rgba[RCOMP] = (UP5(CC_SEL(cc, 11)) + 2 * UP5(CC_SEL(cc, 27))) / 3;
|
||||
rgba[GCOMP] = (UP6(CC_SEL(cc, 5)) + 2 * UP6(CC_SEL(cc, 21))) / 3;
|
||||
rgba[BCOMP] = (UP5(CC_SEL(cc, 0)) + 2 * UP5(CC_SEL(cc, 16))) / 3;
|
||||
}
|
||||
if (acode == 0) {
|
||||
rgba[ACOMP] = alpha0;
|
||||
} else if (acode == 1) {
|
||||
rgba[ACOMP] = alpha1;
|
||||
} else if (alpha0 > alpha1) {
|
||||
rgba[ACOMP] = ((8 - acode) * alpha0 + (acode - 1) * alpha1) / 7;
|
||||
} else if (acode == 6) {
|
||||
rgba[ACOMP] = 0;
|
||||
} else if (acode == 7) {
|
||||
rgba[ACOMP] = 255;
|
||||
} else {
|
||||
rgba[ACOMP] = ((6 - acode) * alpha0 + (acode - 1) * alpha1) / 5;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* DXTn codec
|
||||
* Version: 1.1
|
||||
*
|
||||
* Copyright (C) 2004 Daniel Borca All Rights Reserved.
|
||||
*
|
||||
* this 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* this 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DXTN_H_included
|
||||
#define DXTN_H_included
|
||||
|
||||
TAPI int TAPIENTRY
|
||||
dxt1_rgb_encode (int width, int height, int comps,
|
||||
const void *source, int srcRowStride,
|
||||
void *dest, int destRowStride);
|
||||
|
||||
TAPI int TAPIENTRY
|
||||
dxt1_rgba_encode (int width, int height, int comps,
|
||||
const void *source, int srcRowStride,
|
||||
void *dest, int destRowStride);
|
||||
|
||||
TAPI int TAPIENTRY
|
||||
dxt3_rgba_encode (int width, int height, int comps,
|
||||
const void *source, int srcRowStride,
|
||||
void *dest, int destRowStride);
|
||||
|
||||
TAPI int TAPIENTRY
|
||||
dxt5_rgba_encode (int width, int height, int comps,
|
||||
const void *source, int srcRowStride,
|
||||
void *dest, int destRowStride);
|
||||
|
||||
TAPI void TAPIENTRY
|
||||
dxt1_rgb_decode_1 (const void *texture, int stride /* in pixels */,
|
||||
int i, int j, byte *rgba);
|
||||
|
||||
TAPI void TAPIENTRY
|
||||
dxt1_rgba_decode_1 (const void *texture, int stride /* in pixels */,
|
||||
int i, int j, byte *rgba);
|
||||
|
||||
TAPI void TAPIENTRY
|
||||
dxt3_rgba_decode_1 (const void *texture, int stride /* in pixels */,
|
||||
int i, int j, byte *rgba);
|
||||
|
||||
TAPI void TAPIENTRY
|
||||
dxt5_rgba_decode_1 (const void *texture, int stride /* in pixels */,
|
||||
int i, int j, byte *rgba);
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* FXT1 codec
|
||||
* Version: 1.1
|
||||
*
|
||||
* Copyright (C) 2004 Daniel Borca All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* DANIEL BORCA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FXT1_H_included
|
||||
#define FXT1_H_included
|
||||
|
||||
TAPI int TAPIENTRY
|
||||
fxt1_encode (int width, int height, int comps,
|
||||
const void *source, int srcRowStride,
|
||||
void *dest, int destRowStride);
|
||||
|
||||
TAPI void TAPIENTRY
|
||||
fxt1_decode_1 (const void *texture, int stride /* in pixels */,
|
||||
int i, int j, byte *rgba);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Texture compression
|
||||
* Version: 1.0
|
||||
*
|
||||
* Copyright (C) 2004 Daniel Borca All Rights Reserved.
|
||||
*
|
||||
* this 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* this 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef INTERNAL_H_included
|
||||
#define INTERNAL_H_included
|
||||
|
||||
/*****************************************************************************\
|
||||
* DLL stuff
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifdef __WIN32__
|
||||
#define TAPI __declspec(dllexport)
|
||||
#define TAPIENTRY /*__stdcall*/
|
||||
#else
|
||||
#define TAPI
|
||||
#define TAPIENTRY
|
||||
#endif
|
||||
|
||||
|
||||
/*****************************************************************************\
|
||||
* 64bit types on 32bit machine
|
||||
\*****************************************************************************/
|
||||
|
||||
#if (defined(__GNUC__) && !defined(__cplusplus)) || defined(WIN32)
|
||||
|
||||
typedef unsigned long long qword;
|
||||
|
||||
#define Q_MOV32(a, b) a = b
|
||||
#define Q_OR32(a, b) a |= b
|
||||
#define Q_SHL(a, c) a <<= c
|
||||
|
||||
#else /* !__GNUC__ */
|
||||
|
||||
typedef struct {
|
||||
dword lo, hi;
|
||||
} qword;
|
||||
|
||||
#define Q_MOV32(a, b) a.lo = b
|
||||
#define Q_OR32(a, b) a.lo |= b
|
||||
#define Q_SHL(a, c) \
|
||||
do { \
|
||||
if ((c) >= 32) { \
|
||||
a.hi = a.lo << ((c) - 32); \
|
||||
a.lo = 0; \
|
||||
} else { \
|
||||
a.hi = (a.hi << (c)) | (a.lo >> (32 - (c)));\
|
||||
a.lo <<= c; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif /* !__GNUC__ */
|
||||
|
||||
|
||||
/*****************************************************************************\
|
||||
* Config
|
||||
\*****************************************************************************/
|
||||
|
||||
#define RCOMP 0
|
||||
#define GCOMP 1
|
||||
#define BCOMP 2
|
||||
#define ACOMP 3
|
||||
|
||||
/*****************************************************************************\
|
||||
* Metric
|
||||
\*****************************************************************************/
|
||||
|
||||
#define F(i) (float)1 /* can be used to obtain an oblong metric: 0.30 / 0.59 / 0.11 */
|
||||
#define SAFECDOT 1 /* for paranoids */
|
||||
|
||||
#define MAKEIVEC(NV, NC, IV, B, V0, V1) \
|
||||
do { \
|
||||
/* compute interpolation vector */\
|
||||
float d2 = 0.0F; \
|
||||
float rd2; \
|
||||
\
|
||||
for (i = 0; i < NC; i++) { \
|
||||
IV[i] = (V1[i] - V0[i]) * F(i);\
|
||||
d2 += IV[i] * IV[i]; \
|
||||
} \
|
||||
rd2 = (float)NV / d2; \
|
||||
B = 0; \
|
||||
for (i = 0; i < NC; i++) { \
|
||||
IV[i] *= F(i); \
|
||||
B -= IV[i] * V0[i]; \
|
||||
IV[i] *= rd2; \
|
||||
} \
|
||||
B = B * rd2 + 0.5F; \
|
||||
} while (0)
|
||||
|
||||
#define CALCCDOT(TEXEL, NV, NC, IV, B, V)\
|
||||
do { \
|
||||
float dot = 0.0F; \
|
||||
for (i = 0; i < NC; i++) { \
|
||||
dot += V[i] * IV[i]; \
|
||||
} \
|
||||
TEXEL = (int)(dot + B); \
|
||||
if (SAFECDOT) { \
|
||||
if (TEXEL < 0) { \
|
||||
TEXEL = 0; \
|
||||
} else if (TEXEL > NV) { \
|
||||
TEXEL = NV; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
/*****************************************************************************\
|
||||
* Utility functions
|
||||
\*****************************************************************************/
|
||||
|
||||
void
|
||||
_mesa_upscale_teximage2d (unsigned int inWidth, unsigned int inHeight,
|
||||
unsigned int outWidth, unsigned int outHeight,
|
||||
unsigned int comps,
|
||||
const byte *src, int srcRowStride,
|
||||
unsigned char *dest);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
* Version: 6.3
|
||||
*
|
||||
* Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Copyright (C) 2007 Hiroshi Morii <koolsmoky(at)users.sourceforge.net>
|
||||
* _mesa_upscale_teximage2d speedup
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
void
|
||||
_mesa_upscale_teximage2d (unsigned int inWidth, unsigned int inHeight,
|
||||
unsigned int outWidth, unsigned int outHeight,
|
||||
unsigned int comps,
|
||||
const byte *src, int srcRowStride,
|
||||
byte *dest)
|
||||
{
|
||||
unsigned int i, j, k;
|
||||
|
||||
assert(outWidth >= inWidth);
|
||||
assert(outHeight >= inHeight);
|
||||
|
||||
#if 1 /* H.Morii - faster loops */
|
||||
for (i = 0; i < inHeight; i++) {
|
||||
for (j = 0; j < inWidth; j++) {
|
||||
const int aa = (i * outWidth + j) * comps;
|
||||
const int bb = i * srcRowStride + j * comps;
|
||||
for (k = 0; k < comps; k++) {
|
||||
dest[aa + k] = src[bb + k];
|
||||
}
|
||||
}
|
||||
for (; j < outWidth; j++) {
|
||||
const int aa = (i * outWidth + j) * comps;
|
||||
const int bb = i * srcRowStride + (j - inWidth) * comps;
|
||||
for (k = 0; k < comps; k++) {
|
||||
dest[aa + k] = src[bb + k];
|
||||
}
|
||||
}
|
||||
}
|
||||
for (; i < outHeight; i++) {
|
||||
for (j = 0; j < inWidth; j++) {
|
||||
const int aa = (i * outWidth + j) * comps;
|
||||
const int bb = (i - inHeight) * srcRowStride + j * comps;
|
||||
for (k = 0; k < comps; k++) {
|
||||
dest[aa + k] = src[bb + k];
|
||||
}
|
||||
}
|
||||
for (; j < outWidth; j++) {
|
||||
const int aa = (i * outWidth + j) * comps;
|
||||
const int bb = (i - inHeight) * srcRowStride + (j - inWidth) * comps;
|
||||
for (k = 0; k < comps; k++) {
|
||||
dest[aa + k] = src[bb + k];
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
for (i = 0; i < outHeight; i++) {
|
||||
const int ii = i % inHeight;
|
||||
for (j = 0; j < outWidth; j++) {
|
||||
const int jj = j % inWidth;
|
||||
const int aa = (i * outWidth + j) * comps;
|
||||
const int bb = ii * srcRowStride + jj * comps;
|
||||
for (k = 0; k < comps; k++) {
|
||||
dest[aa + k] = src[bb + k];
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef TYPES_H_included
|
||||
#define TYPES_H_included
|
||||
|
||||
/*****************************************************************************\
|
||||
* 32bit types
|
||||
\*****************************************************************************/
|
||||
typedef unsigned char byte; /* 8-bit */
|
||||
typedef unsigned short word; /* 16-bit */
|
||||
typedef unsigned int dword; /* 32-bit */
|
||||
|
||||
#endif
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Texture compression
|
||||
* Version: 1.0
|
||||
*
|
||||
* Copyright (C) 2004 Daniel Borca All Rights Reserved.
|
||||
*
|
||||
* this 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* this 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "internal.h"
|
||||
#include "dxtn.h"
|
||||
|
||||
|
||||
#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
|
||||
#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
|
||||
#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
|
||||
#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
|
||||
|
||||
|
||||
TAPI void TAPIENTRY
|
||||
fetch_2d_texel_rgb_dxt1 (int texImage_RowStride,
|
||||
const byte *texImage_Data,
|
||||
int i, int j,
|
||||
byte *texel)
|
||||
{
|
||||
dxt1_rgb_decode_1(texImage_Data, texImage_RowStride, i, j, texel);
|
||||
}
|
||||
|
||||
|
||||
TAPI void TAPIENTRY
|
||||
fetch_2d_texel_rgba_dxt1 (int texImage_RowStride,
|
||||
const byte *texImage_Data,
|
||||
int i, int j,
|
||||
byte *texel)
|
||||
{
|
||||
dxt1_rgba_decode_1(texImage_Data, texImage_RowStride, i, j, texel);
|
||||
}
|
||||
|
||||
|
||||
TAPI void TAPIENTRY
|
||||
fetch_2d_texel_rgba_dxt3 (int texImage_RowStride,
|
||||
const byte *texImage_Data,
|
||||
int i, int j,
|
||||
byte *texel)
|
||||
{
|
||||
dxt3_rgba_decode_1(texImage_Data, texImage_RowStride, i, j, texel);
|
||||
}
|
||||
|
||||
|
||||
TAPI void TAPIENTRY
|
||||
fetch_2d_texel_rgba_dxt5 (int texImage_RowStride,
|
||||
const byte *texImage_Data,
|
||||
int i, int j,
|
||||
byte *texel)
|
||||
{
|
||||
dxt5_rgba_decode_1(texImage_Data, texImage_RowStride, i, j, texel);
|
||||
}
|
||||
|
||||
|
||||
TAPI void TAPIENTRY
|
||||
tx_compress_dxtn (int srccomps, int width, int height,
|
||||
const byte *source, int destformat, byte *dest,
|
||||
int destRowStride)
|
||||
{
|
||||
int srcRowStride = width * srccomps;
|
||||
int rv;
|
||||
|
||||
switch (destformat) {
|
||||
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
||||
rv = dxt1_rgb_encode(width, height, srccomps,
|
||||
source, srcRowStride,
|
||||
dest, destRowStride);
|
||||
break;
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
|
||||
rv = dxt1_rgba_encode(width, height, srccomps,
|
||||
source, srcRowStride,
|
||||
dest, destRowStride);
|
||||
break;
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
|
||||
rv = dxt3_rgba_encode(width, height, srccomps,
|
||||
source, srcRowStride,
|
||||
dest, destRowStride);
|
||||
break;
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
||||
rv = dxt5_rgba_encode(width, height, srccomps,
|
||||
source, srcRowStride,
|
||||
dest, destRowStride);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/*return rv;*/
|
||||
}
|
Loading…
Reference in New Issue