| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525 |
- #include "std.h"
- #include "ddutil.h"
- #include "asmcoder.h"
- #include "gxcanvas.h"
- #include "gxruntime.h"
- extern gxRuntime *gx_runtime;
- #include "..\..\freeimage241\source\freeimage.h"
- static AsmCoder asm_coder;
- static void calcShifts( unsigned mask,unsigned char *shr,unsigned char *shl ){
- if( mask ){
- for( *shl=0;!(mask&1);++*shl,mask>>=1 ){}
- for( *shr=8;mask&1;--*shr,mask>>=1 ){}
- }else *shr=*shl=0;
- }
- PixelFormat::~PixelFormat(){
- if( plot_code ){
- VirtualFree( plot_code,0,MEM_RELEASE );
- }
- }
- void PixelFormat::setFormat( const DDPIXELFORMAT &pf ){
- if( plot_code ){
- VirtualFree( plot_code,0,MEM_RELEASE );
- }
- if( !(pf.dwFlags & DDPF_RGB) ){
- memset( this,0,sizeof(*this) );
- return;
- }
- plot_code=(char*)VirtualAlloc( 0,128,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE );
- point_code=plot_code+64;
- depth=pf.dwRGBBitCount;
- amask=pf.dwRGBAlphaBitMask;
- rmask=pf.dwRBitMask;
- gmask=pf.dwGBitMask;
- bmask=pf.dwBBitMask;
- pitch=depth/8;argbfill=0;
- if( !amask ) argbfill|=0xff000000;
- if( !rmask ) argbfill|=0x00ff0000;
- if( !gmask ) argbfill|=0x0000ff00;
- if( !bmask ) argbfill|=0x000000ff;
- calcShifts( amask,&ashr,&ashl );ashr+=24;
- calcShifts( rmask,&rshr,&rshl );rshr+=16;
- calcShifts( gmask,&gshr,&gshl );gshr+=8;
- calcShifts( bmask,&bshr,&bshl );
- plot=(Plot)(void*)plot_code;
- point=(Point)(void*)point_code;
- asm_coder.CodePlot( plot_code,depth,amask,rmask,gmask,bmask );
- asm_coder.CodePoint( point_code,depth,amask,rmask,gmask,bmask );
- }
- static void adjustTexSize( int *width,int *height,IDirect3DDevice7 *dir3dDev ){
- D3DDEVICEDESC7 ddDesc={0};
- if( dir3dDev->GetCaps( &ddDesc )<0 ){
- *width=*height=256;
- return;
- }
- int w=*width,h=*height,min,max;
- //make power of 2
- //Try *always* making POW2 size to fix GF6800 non-pow2 tex issue
- // if( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2 ){
- for( w=1;w<*width;w<<=1 ){}
- for( h=1;h<*height;h<<=1 ){}
- // }
- //make square
- if( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY ){
- if( w>h ) h=w;
- else w=h;
- }
- //check aspect ratio
- if( max=ddDesc.dwMaxTextureAspectRatio ){
- int asp=w>h ? w/h : h/w;
- if( asp>max ){
- if( w>h ) h=w/max;
- else w=h/max;
- }
- }
- //clamp size
- if( (min=ddDesc.dwMinTextureWidth) && w<min ) w=min;
- if( (min=ddDesc.dwMinTextureHeight) && h<min ) h=min;
- if( (max=ddDesc.dwMaxTextureWidth) && w>max ) w=max;
- if( (max=ddDesc.dwMaxTextureHeight) && h>max ) h=max;
- *width=w;*height=h;
- }
- static ddSurf *createSurface( int width,int height,int pitch,void *bits,IDirectDraw7 *dirDraw ){
- DDSURFACEDESC2 desc={sizeof(desc)};
- desc.dwFlags=DDSD_WIDTH|DDSD_HEIGHT|DDSD_LPSURFACE|DDSD_PITCH|DDSD_PIXELFORMAT|DDSD_CAPS;
- desc.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY;
- desc.dwWidth=width;desc.dwHeight=height;
- desc.lPitch=pitch;desc.lpSurface=bits;
- desc.ddpfPixelFormat.dwSize=sizeof(DDPIXELFORMAT);
- desc.ddpfPixelFormat.dwFlags=DDPF_RGB|DDPF_ALPHAPIXELS;
- desc.ddpfPixelFormat.dwRGBBitCount=32;
- desc.ddpfPixelFormat.dwRBitMask=0xff0000;
- desc.ddpfPixelFormat.dwGBitMask=0x00ff00;
- desc.ddpfPixelFormat.dwBBitMask=0x0000ff;
- desc.ddpfPixelFormat.dwRGBAlphaBitMask=0xff000000;
- ddSurf *surf;
- if( dirDraw->CreateSurface( &desc,&surf,0 )>=0 ) return surf;
- return 0;
- }
- static void buildMask( ddSurf *surf ){
- DDSURFACEDESC2 desc={sizeof(desc)};
- surf->Lock( 0,&desc,DDLOCK_WAIT,0 );
- unsigned char *surf_p=(unsigned char*)desc.lpSurface;
- PixelFormat fmt( desc.ddpfPixelFormat );
- for( int y=0;y<desc.dwHeight;++y ){
- unsigned char *p=surf_p;
- for( int x=0;x<desc.dwWidth;++x ){
- unsigned argb=fmt.getPixel( p );
- unsigned rgb=argb&0xffffff;
- unsigned a=rgb ? 0xff000000 : 0;
- fmt.setPixel( p,a|rgb );
- p+=fmt.getPitch();
- }
- surf_p+=desc.lPitch;
- }
- surf->Unlock( 0 );
- }
- static void buildAlpha( ddSurf *surf,bool whiten ){
- DDSURFACEDESC2 desc={sizeof(desc)};
- surf->Lock( 0,&desc,DDLOCK_WAIT,0 );
- unsigned char *surf_p=(unsigned char*)desc.lpSurface;
- PixelFormat fmt( desc.ddpfPixelFormat );
- for( int y=0;y<desc.dwHeight;++y ){
- unsigned char *p=surf_p;
- for( int x=0;x<desc.dwWidth;++x ){
- unsigned argb=fmt.getPixel( p );
- unsigned alpha=(((argb>>16)&0xff)+((argb>>8)&0xff)+(argb&0xff))/3;
- argb=(alpha<<24) | (argb & 0xffffff);
- if( whiten ) argb|=0xffffff;
- fmt.setPixel( p,argb );
- p+=fmt.getPitch();
- }
- surf_p+=desc.lPitch;
- }
- surf->Unlock( 0 );
- }
- void ddUtil::buildMipMaps( ddSurf *surf ){
- DDSURFACEDESC2 desc={sizeof(desc)};
- surf->GetSurfaceDesc( &desc );
- if( !(desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE) ) return;
- if( !(desc.ddpfPixelFormat.dwFlags & DDPF_RGB) ) return;
- DDSCAPS2 caps={0};
- caps.dwCaps=DDSCAPS_TEXTURE;
- caps.dwCaps2=DDSCAPS2_MIPMAPSUBLEVEL;
- IDirectDrawSurface7 *src=surf,*dest;
- while( src->GetAttachedSurface( &caps,&dest )>=0 ){
- DDSURFACEDESC2 src_desc={sizeof(src_desc)};
- if( src->Lock( 0,&src_desc,DDLOCK_WAIT,0 )<0 ) abort();
- unsigned char *src_p=(unsigned char*)src_desc.lpSurface;
- PixelFormat src_fmt( src_desc.ddpfPixelFormat );
- DDSURFACEDESC2 dest_desc={sizeof(dest_desc)};
- if( dest->Lock( 0,&dest_desc,DDLOCK_WAIT,0 )<0 ) abort();
- unsigned char *dest_p=(unsigned char *)dest_desc.lpSurface;
- PixelFormat dest_fmt( dest_desc.ddpfPixelFormat );
- if( src_desc.dwWidth==1 ){
- for( int y=0;y<dest_desc.dwHeight;++y ){
- unsigned p1=src_fmt.getPixel( src_p );
- unsigned p2=src_fmt.getPixel( src_p+src_desc.lPitch );
- unsigned argb=
- ((p1&0xfefefefe)>>1)+((p2&0xfefefefe)>>1);
- argb+=( (
- (p1&0x01010101)+(p2&0x01010101) )>>1 ) & 0x01010101;
- dest_fmt.setPixel( dest_p,argb );
- src_p+=src_desc.lPitch*2;
- dest_p+=dest_desc.lPitch;
- }
- }else if( src_desc.dwHeight==1 ){
- for( int x=0;x<dest_desc.dwWidth;++x ){
- unsigned p1=src_fmt.getPixel( src_p );
- unsigned p2=src_fmt.getPixel( src_p+src_fmt.getPitch() );
- unsigned argb=
- ((p1&0xfefefefe)>>1)+((p2&0xfefefefe)>>1);
- argb+=( (
- (p1&0x01010101)+(p2&0x01010101) )>>1 ) & 0x01010101;
- dest_fmt.setPixel( dest_p,argb );
- src_p+=src_fmt.getPitch()*2;
- dest_p+=dest_fmt.getPitch();
- }
- }else{
- for( int y=0;y<dest_desc.dwHeight;++y ){
- unsigned char *src_t=src_p;
- unsigned char *dest_t=dest_p;
- for( int x=0;x<dest_desc.dwWidth;++x ){
- unsigned p1=src_fmt.getPixel( src_t );
- unsigned p2=src_fmt.getPixel( src_t+src_fmt.getPitch() );
- unsigned p3=src_fmt.getPixel( src_t+src_desc.lPitch+src_fmt.getPitch() );
- unsigned p4=src_fmt.getPixel( src_t+src_desc.lPitch );
- unsigned argb=
- ((p1&0xfcfcfcfc)>>2)+((p2&0xfcfcfcfc)>>2)+
- ((p3&0xfcfcfcfc)>>2)+((p4&0xfcfcfcfc)>>2);
- argb+=( (
- (p1&0x03030303)+(p2&0x03030303)+
- (p3&0x03030303)+(p4&0x03030303) )>>2 ) & 0x03030303;
- dest_fmt.setPixel( dest_t,argb );
- src_t+=src_fmt.getPitch()*2;
- dest_t+=dest_fmt.getPitch();
- }
- src_p+=src_desc.lPitch*2;
- dest_p+=dest_desc.lPitch;
- }
- }
- src->Unlock( 0 );
- dest->Unlock( 0 );
- dest->Release();
- src=dest;
- }
- }
- void ddUtil::copy( ddSurf *dest,int dx,int dy,int dw,int dh,ddSurf *src,int sx,int sy,int sw,int sh ){
- DDSURFACEDESC2 src_desc={sizeof(src_desc)};
- src->Lock( 0,&src_desc,DDLOCK_WAIT,0 );
- PixelFormat src_fmt( src_desc.ddpfPixelFormat );
- unsigned char *src_p=(unsigned char*)src_desc.lpSurface;
- src_p+=src_desc.lPitch*sy+src_fmt.getPitch()*sx;
- DDSURFACEDESC2 dest_desc={sizeof(dest_desc)};
- dest->Lock( 0,&dest_desc,DDLOCK_WAIT,0 );
- PixelFormat dest_fmt( dest_desc.ddpfPixelFormat );
- unsigned char *dest_p=(unsigned char *)dest_desc.lpSurface;
- dest_p+=dest_desc.lPitch*dy+dest_fmt.getPitch()*dx;
- for( int y=0;y<dh;++y ){
- unsigned char *dest=dest_p;
- unsigned char *src=src_p+src_desc.lPitch*(y*sh/dh);
- for( int x=0;x<dw;++x ){
- dest_fmt.setPixel( dest,src_fmt.getPixel( src+src_fmt.getPitch()*(x*sw/dw) ) );
- dest+=dest_fmt.getPitch();
- }
- dest_p+=dest_desc.lPitch;
- }
- src->Unlock( 0 );
- dest->Unlock( 0 );
- }
- ddSurf *ddUtil::createSurface( int w,int h,int flags,gxGraphics *gfx ){
- DDSURFACEDESC2 desc={sizeof(desc)};
- desc.dwFlags=DDSD_CAPS;
- int hi=flags & gxCanvas::CANVAS_TEX_HICOLOR?1:0;
- if( w ){ desc.dwWidth=w;desc.dwFlags|=DDSD_WIDTH; }
- if( h ){ desc.dwHeight=h;desc.dwFlags|=DDSD_HEIGHT; }
- if( flags & gxCanvas::CANVAS_TEX_MASK ){
- desc.dwFlags|=DDSD_PIXELFORMAT;
- desc.ddpfPixelFormat=gfx->texRGBMaskFmt[hi];
- }else if( flags & gxCanvas::CANVAS_TEX_RGB ){
- desc.dwFlags|=DDSD_PIXELFORMAT;
- desc.ddpfPixelFormat=(flags&gxCanvas::CANVAS_TEX_ALPHA)?gfx->texRGBAlphaFmt[hi]:gfx->texRGBFmt[hi];
- }else if( flags & gxCanvas::CANVAS_TEX_ALPHA ){
- desc.dwFlags|=DDSD_PIXELFORMAT;
- desc.ddpfPixelFormat=gfx->texAlphaFmt[hi];
- }else if( flags & gxCanvas::CANVAS_TEXTURE ){
- desc.dwFlags|=DDSD_PIXELFORMAT;
- desc.ddpfPixelFormat=gfx->primFmt;
- }
- if( flags & gxCanvas::CANVAS_TEXTURE ){
- desc.ddsCaps.dwCaps|=DDSCAPS_TEXTURE;
- if( !(flags & gxCanvas::CANVAS_TEX_VIDMEM) ){
- desc.ddsCaps.dwCaps2|=DDSCAPS2_TEXTUREMANAGE;
- if( flags & gxCanvas::CANVAS_TEX_MIPMAP ){
- desc.ddsCaps.dwCaps|=DDSCAPS_MIPMAP|DDSCAPS_COMPLEX;
- }
- }
- if( flags & (gxCanvas::CANVAS_TEX_CUBE) ){
- desc.ddsCaps.dwCaps|=DDSCAPS_COMPLEX;
- desc.ddsCaps.dwCaps2|=DDSCAPS2_CUBEMAP|DDSCAPS2_CUBEMAP_ALLFACES;
- }
- adjustTexSize( (int*)&desc.dwWidth,(int*)&desc.dwHeight,gfx->dir3dDev );
- }else{
- desc.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN;
- if( flags & gxCanvas::CANVAS_HIGHCOLOR ){
- desc.dwFlags|=DDSD_PIXELFORMAT;
- desc.ddsCaps.dwCaps|=DDSCAPS_SYSTEMMEMORY;
- desc.ddpfPixelFormat.dwSize=sizeof(DDPIXELFORMAT);
- desc.ddpfPixelFormat.dwFlags=DDPF_RGB|DDPF_ALPHAPIXELS;
- desc.ddpfPixelFormat.dwRGBBitCount=32;
- desc.ddpfPixelFormat.dwRBitMask=0xff0000;
- desc.ddpfPixelFormat.dwGBitMask=0x00ff00;
- desc.ddpfPixelFormat.dwBBitMask=0x0000ff;
- desc.ddpfPixelFormat.dwRGBAlphaBitMask=0xff000000;
- }else if( flags & gxCanvas::CANVAS_NONDISPLAY ){
- desc.ddsCaps.dwCaps|=DDSCAPS_SYSTEMMEMORY;
- }
- }
- ddSurf *surf;
- if( gfx->dirDraw->CreateSurface( &desc,&surf,0 )>=0 ) return surf;
- if( desc.ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN ){
- if( !(desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) ){
- //try again in system memory!
- desc.ddsCaps.dwCaps|=DDSCAPS_SYSTEMMEMORY;
- if( gfx->dirDraw->CreateSurface( &desc,&surf,0 )>=0 ) return surf;
- }
- }
- return 0;
- }
- //Tom Speed's DXTC loader
- //
- IDirectDrawSurface7 *loadDXTC(const char* filename,gxGraphics *gfx)
- {
- HRESULT hr;
- DDSURFACEDESC2 ddsd;
- DDSURFACEDESC2 fileddsd;
- char magicID[4];
- FILE *fp;
- /* try to open the file */
- fp = fopen(filename, "rb");
- if(!fp) return NULL;
- /* valid DDS? */
- fread(magicID, 1, 4, fp);
- if (strncmp(magicID, "DDS ", 4) != 0)
- {
- fclose(fp);
- return NULL;
- }
- /* get the DXTC file surface description */
- fread(&fileddsd, sizeof(DDSURFACEDESC2), 1, fp);
- if (fileddsd.dwSize != sizeof(DDSURFACEDESC2))
- {
- fclose(fp);
- return NULL;
- }
- /* copy the fileddsd before we manipulate it so you
- can get neccessary info you want about it later */
- memcpy(&ddsd, &fileddsd,sizeof(DDSURFACEDESC2));
- /* remove unwanted flags if they exist */
- //not sure if this is needed, works without it though
- //ddsd.dwFlags &= ~DDSD_LINEARSIZE;
- int blockSize = 0;
- int chunkSize = 0;
- if(ddsd.ddpfPixelFormat.dwFourCC == FOURCC_DXT1)
- blockSize = 8; // DXT1
- if(ddsd.ddpfPixelFormat.dwFourCC == FOURCC_DXT3)
- blockSize = 16; // DXT3
- if(ddsd.ddpfPixelFormat.dwFourCC == FOURCC_DXT5)
- blockSize = 16; // DXT5
- /* if it isn't a format we support, exit */
- if (blockSize == 0)
- {
- fclose(fp);
- return NULL;
- }
- /* add texture manage flag */
- ddsd.ddsCaps.dwCaps2|=DDSCAPS2_TEXTUREMANAGE;
- /* Create the new DXTC surface using the DDSURFACEDESC2
- we read in from the file */
- IDirectDrawSurface7 * newSurf = NULL;
- hr = gfx->dirDraw->CreateSurface(&ddsd, &newSurf, NULL);
- if(FAILED(hr))
- {
- fclose(fp);
- return NULL;
- }
- /* Define what type of child surfaces we may wish
- to access, in this case MipMaps */
- DDSCAPS2 mipmapddsd;
- ZeroMemory(&mipmapddsd,sizeof(DDSCAPS2));
- mipmapddsd.dwCaps = DDSCAPS_TEXTURE|DDSCAPS_MIPMAP|DDSCAPS_COMPLEX;
- /* pointers used when iterating through mipmaps */
- IDirectDrawSurface7 *topDDS = NULL;
- IDirectDrawSurface7 *nextDDS = NULL;
- topDDS = newSurf;
- topDDS->AddRef();
- while(TRUE)
- {
- /* get a description of this surface */
- hr = topDDS->Lock(NULL,&ddsd,DDLOCK_WAIT,NULL);
- if(FAILED(hr))
- {
- fclose(fp);
- topDDS->Release();
- newSurf->Release();
- nextDDS->Release();
- return NULL;
- }
- /* how big the raw data is for this surface */
- chunkSize = ((ddsd.dwWidth+3)/4) * ((ddsd.dwHeight+3)/4) * blockSize;
- /* read in the raw DXTC surface data */
- if(!fread(ddsd.lpSurface, chunkSize, 1, fp))
- {
- fclose(fp);
- topDDS->Release();
- newSurf->Release();
- nextDDS->Release();
- return NULL;
- }
- topDDS->Unlock(NULL);
- /* Get next mipmap in chain, or exit the loop if there's no more */
- hr = topDDS->GetAttachedSurface(&mipmapddsd,&nextDDS);
- if(FAILED(hr))
- {
- fclose(fp);
- topDDS->Release();
- break;
- }
- topDDS->Release();
- topDDS = nextDDS;
- nextDDS->Release();
- }
- return newSurf;
- }
- ddSurf *ddUtil::loadSurface( const std::string &f,int flags,gxGraphics *gfx ){
- int i=f.find( ".dds" );
- if( i!=string::npos && i+4==f.size() ){
- //dds file!
- ddSurf *surf=loadDXTC( f.c_str(),gfx );
- return surf;
- }
- FreeImage_Initialise();
- FREE_IMAGE_FORMAT fmt=FreeImage_GetFileType( f.c_str(),f.size() );
- if( fmt==FIF_UNKNOWN ){
- int n=f.find( "." );if( n==string::npos ) return 0;
- fmt=FreeImage_GetFileTypeFromExt( f.substr(n+1).c_str() );
- if( fmt==FIF_UNKNOWN ) return 0;
- }
- FIBITMAP *t_dib=FreeImage_Load( fmt,f.c_str(),0 );
- if( !t_dib ) return 0;
- bool trans=FreeImage_GetBPP( t_dib )==32 || FreeImage_IsTransparent( t_dib );
- FIBITMAP *dib=FreeImage_ConvertTo32Bits( t_dib );
-
- if( dib ) FreeImage_Unload( t_dib );
- else dib=t_dib;
- int width=FreeImage_GetWidth(dib);
- int height=FreeImage_GetHeight(dib);
- int pitch=FreeImage_GetPitch(dib);
- void *bits=FreeImage_GetBits(dib);
- ddSurf *src=::createSurface( width,height,pitch,bits,gfx->dirDraw );
- if( !src ){
- FreeImage_Unload( dib );
- return 0;
- }
- if( flags & gxCanvas::CANVAS_TEX_ALPHA ){
- if( flags & gxCanvas::CANVAS_TEX_MASK ){
- buildMask( src );
- }else if( !trans ){
- buildAlpha( src,(flags & gxCanvas::CANVAS_TEX_RGB)?false:true );
- }
- }else{
- unsigned char *p=(unsigned char *)bits;
- for( int k=0;k<height;++k ){
- unsigned char *t=p+3;
- for( int j=0;j<width;++j ){
- *t=0xff;t+=4;
- }
- p+=pitch;
- }
- }
- ddSurf *dest=createSurface( width,height,flags,gfx );
- if( !dest ){
- src->Release();
- FreeImage_Unload( dib );
- return 0;
- }
- int t_w=width,t_h=height;
- if( flags & gxCanvas::CANVAS_TEXTURE ) adjustTexSize( &t_w,&t_h,gfx->dir3dDev );
- copy( dest,0,0,t_w,t_h,src,0,height-1,width,-height );
- src->Release();
- FreeImage_Unload( dib );
- return dest;
- }
|