| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619 |
- #include "std.h"
- #include "gxgraphics.h"
- #include "gxruntime.h"
- extern gxRuntime *gx_runtime;
- gxGraphics::gxGraphics( gxRuntime *rt,IDirectDraw7 *dd,IDirectDrawSurface7 *fs,IDirectDrawSurface7 *bs,bool d3d ):
- runtime(rt),dirDraw(dd),dir3d(0),dir3dDev(0),def_font(0),gfx_lost(false),dummy_mesh(0){
- dirDraw->QueryInterface( IID_IDirectDraw,(void**)&ds_dirDraw );
- front_canvas=d_new gxCanvas( this,fs,0 );
- back_canvas=d_new gxCanvas( this,bs,0 );
- front_canvas->cls();
- back_canvas->cls();
- def_font=loadFont( "courier",12,0 );
- front_canvas->setFont( def_font );
- back_canvas->setFont( def_font );
- memset(&primFmt,0,sizeof(primFmt));
- primFmt.dwSize=sizeof(primFmt);
- fs->GetPixelFormat( &primFmt );
- //are we fullscreen?
- _gamma=0;
- if( fs!=bs ){
- if( fs->QueryInterface( IID_IDirectDrawGammaControl,(void**)&_gamma )>=0 ){
- if( _gamma->GetGammaRamp( 0,&_gammaRamp )<0 ) _gamma=0;
- }
- }
- if( !_gamma ){
- for( int k=0;k<256;++k ) _gammaRamp.red[k]=_gammaRamp.blue[k]=_gammaRamp.green[k]=k;
- }
- }
- gxGraphics::~gxGraphics(){
- if( _gamma ) _gamma->Release();
- #ifdef PRO
- while( scene_set.size() ) freeScene( *scene_set.begin() );
- #endif
- while( movie_set.size() ) closeMovie( *movie_set.begin() );
- while( font_set.size() ) freeFont( *font_set.begin() );
- while( canvas_set.size() ) freeCanvas( *canvas_set.begin() );
- set<string>::iterator it;
- for( it=font_res.begin();it!=font_res.end();++it ) RemoveFontResource( (*it).c_str() );
- font_res.clear();
- delete back_canvas;
- delete front_canvas;
- ds_dirDraw->Release();
- dirDraw->RestoreDisplayMode();
- dirDraw->Release();
- }
- void gxGraphics::setGamma( int r,int g,int b,float dr,float dg,float db ){
- _gammaRamp.red[r&255]=dr*257.0f;
- _gammaRamp.green[g&255]=dg*257.0f;
- _gammaRamp.blue[b&255]=db*257.0f;
- }
- void gxGraphics::updateGamma( bool calibrate ){
- if( !_gamma ) return;
- _gamma->SetGammaRamp( calibrate ? DDSGR_CALIBRATE : 0,&_gammaRamp );
- }
- void gxGraphics::getGamma( int r,int g,int b,float *dr,float *dg,float *db ){
- *dr=_gammaRamp.red[r&255]/257.0f;
- *dg=_gammaRamp.green[g&255]/257.0f;
- *db=_gammaRamp.blue[b&255]/257.0f;
- }
- void gxGraphics::backup(){
- }
- bool gxGraphics::restore(){
- while( dirDraw->TestCooperativeLevel()!=DD_OK ){
- if( dirDraw->TestCooperativeLevel()==DDERR_WRONGMODE ) return false;
- Sleep( 100 );
- }
- if( back_canvas->getSurface()->IsLost()==DD_OK ) return true;
- dirDraw->RestoreAllSurfaces();
- //restore all canvases
- set<gxCanvas*>::iterator it;
- for( it=canvas_set.begin();it!=canvas_set.end();++it ){
- (*it)->restore();
- }
- #ifdef PRO
- //restore all meshes (b3d surfaces)
- set<gxMesh*>::iterator mesh_it;
- for( mesh_it=mesh_set.begin();mesh_it!=mesh_set.end();++mesh_it ){
- (*mesh_it)->restore();
- }
- if( dir3d ) dir3d->EvictManagedTextures();
- #endif
- return true;
- }
- gxCanvas *gxGraphics::getFrontCanvas()const{
- return front_canvas;
- }
- gxCanvas *gxGraphics::getBackCanvas()const{
- return back_canvas;
- }
- gxFont *gxGraphics::getDefaultFont()const{
- return def_font;
- }
- void gxGraphics::vwait(){
- dirDraw->WaitForVerticalBlank( DDWAITVB_BLOCKBEGIN,0 );
- }
- void gxGraphics::flip( bool v ){
- runtime->flip( v );
- }
- void gxGraphics::copy( gxCanvas *dest,int dx,int dy,int dw,int dh,gxCanvas *src,int sx,int sy,int sw,int sh ){
- RECT r={ dx,dy,dx+dw,dy+dh };
- ddUtil::copy( dest->getSurface(),dx,dy,dw,dh,src->getSurface(),sx,sy,sw,sh );
- dest->damage( r );
- }
- int gxGraphics::getScanLine()const{
- DWORD t=0;
- dirDraw->GetScanLine( &t );
- return t;
- }
- int gxGraphics::getTotalVidmem()const{
- DDCAPS caps={sizeof(caps)};
- dirDraw->GetCaps( &caps,0 );
- return caps.dwVidMemTotal;
- }
- int gxGraphics::getAvailVidmem()const{
- DDCAPS caps={sizeof(caps)};
- dirDraw->GetCaps( &caps,0 );
- return caps.dwVidMemFree;
- }
- gxMovie *gxGraphics::openMovie( const string &file,int flags ){
- IAMMultiMediaStream *iam_stream;
- if( CoCreateInstance(
- CLSID_AMMultiMediaStream,NULL,CLSCTX_INPROC_SERVER,
- IID_IAMMultiMediaStream,(void **)&iam_stream )==S_OK ){
- if( iam_stream->Initialize( STREAMTYPE_READ,AMMSF_NOGRAPHTHREAD,NULL )==S_OK ){
- if( iam_stream->AddMediaStream( ds_dirDraw,&MSPID_PrimaryVideo,0,NULL )==S_OK ){
- iam_stream->AddMediaStream( NULL,&MSPID_PrimaryAudio,AMMSF_ADDDEFAULTRENDERER,NULL );
- WCHAR *path=new WCHAR[ file.size()+1 ];
- MultiByteToWideChar( CP_ACP,0,file.c_str(),-1,path,sizeof(WCHAR)*(file.size()+1) );
- int n=iam_stream->OpenFile( path,0 );
- delete path;
- if( n==S_OK ){
- gxMovie *movie=d_new gxMovie( this,iam_stream );
- movie_set.insert( movie );
- return movie;
- }
- }
- }
- iam_stream->Release();
- }
- return 0;
- }
- gxMovie *gxGraphics::verifyMovie( gxMovie *m ){
- return movie_set.count( m ) ? m : 0;
- }
- void gxGraphics::closeMovie( gxMovie *m ){
- if( movie_set.erase( m ) ) delete m;
- }
- gxCanvas *gxGraphics::createCanvas( int w,int h,int flags ){
- ddSurf *s=ddUtil::createSurface( w,h,flags,this );
- if( !s ) return 0;
- gxCanvas *c=d_new gxCanvas( this,s,flags );
- canvas_set.insert( c );
- c->cls();
- return c;
- }
- gxCanvas *gxGraphics::loadCanvas( const string &f,int flags ){
- ddSurf *s=ddUtil::loadSurface( f,flags,this );
- if( !s ) return 0;
- gxCanvas *c=d_new gxCanvas( this,s,flags );
- canvas_set.insert( c );
- return c;
- }
- gxCanvas *gxGraphics::verifyCanvas( gxCanvas *c ){
- return canvas_set.count( c ) || c==front_canvas || c==back_canvas ? c : 0;
- }
- void gxGraphics::freeCanvas( gxCanvas *c ){
- if( canvas_set.erase( c ) ) delete c;
- }
- int gxGraphics::getWidth()const{
- return front_canvas->getWidth();
- }
- int gxGraphics::getHeight()const{
- return front_canvas->getHeight();
- }
- int gxGraphics::getDepth()const{
- return front_canvas->getDepth();
- }
- gxFont *gxGraphics::loadFont( const string &f,int height,int flags ){
- int bold=flags & gxFont::FONT_BOLD ? FW_BOLD : FW_REGULAR;
- int italic=flags & gxFont::FONT_ITALIC ? 1 : 0;
- int underline=flags & gxFont::FONT_UNDERLINE ? 1 : 0;
- int strikeout=0;
- string t;
- int n=f.find('.');
- if( n!=string::npos ){
- t=fullfilename(f);
- if( !font_res.count(t) && AddFontResource( t.c_str() ) ) font_res.insert( t );
- t=filenamefile( f.substr(0,n) );
- }else{
- t=f;
- }
- //save and turn off font smoothing....
- BOOL smoothing=FALSE;
- SystemParametersInfo( SPI_GETFONTSMOOTHING,0,&smoothing,0 );
- SystemParametersInfo( SPI_SETFONTSMOOTHING,FALSE,0,0 );
- HFONT hfont=CreateFont(
- height,0,0,0,
- bold,italic,underline,strikeout,
- ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,
- DEFAULT_PITCH|FF_DONTCARE,t.c_str() );
- if( !hfont ){
- //restore font smoothing
- SystemParametersInfo( SPI_SETFONTSMOOTHING,smoothing,0,0 );
- return 0;
- }
- HDC hdc=CreateCompatibleDC( 0 );
- HFONT pfont=(HFONT)SelectObject( hdc,hfont );
- TEXTMETRIC tm={0};
- if( !GetTextMetrics( hdc,&tm ) ){
- SelectObject( hdc,pfont );
- DeleteDC( hdc );
- DeleteObject( hfont );
- SystemParametersInfo( SPI_SETFONTSMOOTHING,smoothing,0,0 );
- return 0;
- }
- height=tm.tmHeight;
- int first=tm.tmFirstChar,last=tm.tmLastChar;
- int sz=last-first+1;
- int *offs=d_new int[sz];
- int *widths=d_new int[sz];
- int *as=d_new int[sz];
- //calc size of canvas to hold font.
- int x=0,y=0,max_x=0;
- for( int k=0;k<sz;++k ){
- char t=k+first;
- SIZE sz;
- GetTextExtentPoint32( hdc,&t,1,&sz );
- int w=sz.cx;
- as[k]=0;
- ABC abc;
- if( GetCharABCWidths( hdc,t,t,&abc ) ){
- if( abc.abcA<0 ){
- as[k]=ceil(-abc.abcA);
- w+=as[k];
- }
- if( abc.abcC<0 ) w+=ceil(-abc.abcC);
- }
- if( x && x+w>getWidth() ){ x=0;y+=height; }
- offs[k]=(x<<16)|y;
- widths[k]=w;
- x+=w;if( x>max_x ) max_x=x;
- }
- SelectObject( hdc,pfont );
- DeleteDC( hdc );
- int cw=max_x,ch=y+height;
- if( gxCanvas *c=createCanvas( cw,ch,0 ) ){
- ddSurf *surf=c->getSurface();
- HDC surf_hdc;
- if( surf->GetDC( &surf_hdc )>=0 ){
- HFONT pfont=(HFONT)SelectObject( surf_hdc,hfont );
- SetBkColor( surf_hdc,0x000000 );
- SetTextColor( surf_hdc,0xffffff );
- for( int k=0;k<sz;++k ){
- int x=(offs[k]>>16)&0xffff,y=offs[k]&0xffff;
- char t=k+first;
- RECT rect={x,y,x+widths[k],y+height};
- ExtTextOut( surf_hdc,x+as[k],y,ETO_CLIPPED,&rect,&t,1,0 );
- }
- SelectObject( surf_hdc,pfont );
- surf->ReleaseDC( surf_hdc );
- DeleteObject( hfont );
- delete[] as;
- c->backup();
- gxFont *font=d_new gxFont( this,c,tm.tmMaxCharWidth,height,first,last+1,tm.tmDefaultChar,offs,widths );
- font_set.insert( font );
- //restore font smoothing
- SystemParametersInfo( SPI_SETFONTSMOOTHING,smoothing,0,0 );
- return font;
- }else{
- }
- freeCanvas( c );
- }else{
- }
- DeleteObject( hfont );
- delete[] as;
- delete[] widths;
- delete[] offs;
- //restore font smoothing
- SystemParametersInfo( SPI_SETFONTSMOOTHING,smoothing,0,0 );
- return 0;
- }
- gxFont *gxGraphics::verifyFont( gxFont *f ){
- return font_set.count( f ) ? f : 0;
- }
- void gxGraphics::freeFont( gxFont *f ){
- if( font_set.erase( f ) ) delete f;
- }
- //////////////
- // 3D STUFF //
- //////////////
- #ifdef PRO
- static int maxDevType;
- static HRESULT CALLBACK enumDevice( char *desc,char *name,D3DDEVICEDESC7 *devDesc,void *context ){
- gxGraphics *g=(gxGraphics*)context;
- int t=0;
- GUID guid=devDesc->deviceGUID;
- if( guid==IID_IDirect3DRGBDevice ) t=1;
- else if( guid==IID_IDirect3DHALDevice ) t=2;
- else if( guid==IID_IDirect3DTnLHalDevice ) t=3;
- if( t>maxDevType ){
- g->dir3dDevDesc=*devDesc;
- maxDevType=t;
- }
- return D3DENUMRET_OK;
- }
- static HRESULT CALLBACK enumZbuffFormat( LPDDPIXELFORMAT format,void *context ){
- gxGraphics *g=(gxGraphics*)context;
- if( format->dwZBufferBitDepth==g->primFmt.dwRGBBitCount ){
- g->zbuffFmt=*format;
- return D3DENUMRET_CANCEL;
- }
- if( format->dwZBufferBitDepth>g->zbuffFmt.dwZBufferBitDepth ){
- if( format->dwZBufferBitDepth<g->primFmt.dwRGBBitCount ){
- g->zbuffFmt=*format;
- }
- }
- return D3DENUMRET_OK;
- }
- struct TexFmt{
- DDPIXELFORMAT fmt;
- int bits,a_bits,rgb_bits;
- };
- static int cntBits( int mask ){
- int n=0;
- for( int k=0;k<32;++k ){
- if( mask & (1<<k) ) ++n;
- }
- return n;
- }
- static vector<TexFmt> tex_fmts;
- static HRESULT CALLBACK enumTextureFormat( DDPIXELFORMAT *fmt,void *p ){
- TexFmt t;
- t.fmt=*fmt;
- t.bits=fmt->dwRGBBitCount;
- t.a_bits=(fmt->dwFlags & DDPF_ALPHAPIXELS) ? cntBits(fmt->dwRGBAlphaBitMask) : 0;
- t.rgb_bits=(fmt->dwFlags & DDPF_RGB) ? cntBits(fmt->dwRBitMask|fmt->dwGBitMask|fmt->dwBBitMask) : 0;
- tex_fmts.push_back( t );
- return D3DENUMRET_OK;
- }
- static string itobin( int n ){
- string t;
- for( int k=0;k<32;n<<=1,++k ){
- t+=(n&0x80000000) ? '1' : '0';
- }
- return t;
- }
- static void debugPF( const DDPIXELFORMAT &pf ){
- string t;
- t="Bits:"+itoa( pf.dwRGBBitCount );
- gx_runtime->debugLog( t.c_str() );
- t="R Mask:"+itobin( pf.dwRBitMask );
- gx_runtime->debugLog( t.c_str() );
- t="G Mask:"+itobin( pf.dwGBitMask );
- gx_runtime->debugLog( t.c_str() );
- t="B Mask:"+itobin( pf.dwBBitMask );
- gx_runtime->debugLog( t.c_str() );
- t="A Mask:"+itobin( pf.dwRGBAlphaBitMask );
- gx_runtime->debugLog( t.c_str() );
- }
- static void pickTexFmts( gxGraphics *g,int hi ){
- //texRGBFmt.
- {
- int pick=-1,max=0,bits;
- for( int d=g->primFmt.dwRGBBitCount;d<=32;d+=8 ){
- for( int k=0;k<tex_fmts.size();++k ){
- const TexFmt &t=tex_fmts[k];
- if( t.bits>d || !t.rgb_bits || t.rgb_bits<max ) continue;
- if( t.rgb_bits==max && t.bits>=bits ) continue;
- pick=k;max=t.rgb_bits;bits=t.bits;
- }
- if( !hi && pick>=0 ) break;
- }
- if( pick<0 ) g->texRGBFmt[hi]=g->primFmt;
- else g->texRGBFmt[hi]=tex_fmts[pick].fmt;
- }
- //texAlphaFmt
- {
- int pick=-1,max=0,bits;
- for( int d=g->primFmt.dwRGBBitCount;d<=32;d+=8 ){
- for( int k=0;k<tex_fmts.size();++k ){
- const TexFmt &t=tex_fmts[k];
- if( t.bits>d || !t.a_bits || t.a_bits<max ) continue;
- if( t.a_bits==max && t.bits>=bits ) continue;
- pick=k;max=t.a_bits;bits=t.bits;
- }
- if( !hi && pick>=0 ) break;
- }
- if( pick<0 ) g->texAlphaFmt[hi]=g->primFmt;
- else g->texAlphaFmt[hi]=tex_fmts[pick].fmt;
- }
- //texRGBAlphaFmt
- {
- int pick=-1,a8rgb8=-1,max=0,bits;
- for( int d=g->primFmt.dwRGBBitCount;d<=32;d+=8 ){
- for( int k=0;k<tex_fmts.size();++k ){
- const TexFmt &t=tex_fmts[k];
- if( t.a_bits==8 && t.bits==16 ){ a8rgb8=k;continue; }
- if( t.bits>d || !t.a_bits || !t.rgb_bits || t.a_bits<max ) continue;
- if( t.a_bits==max && t.bits>=bits ) continue;
- pick=k;max=t.a_bits;bits=t.bits;
- }
- if( !hi && pick>=0 ) break;
- }
- if( pick<0 ) pick=a8rgb8;
- if( pick<0 ) g->texRGBAlphaFmt[hi]=g->primFmt;
- else g->texRGBAlphaFmt[hi]=tex_fmts[pick].fmt;
- }
- //texRGBMaskFmt...
- {
- int pick=-1,max=0,bits;
- for( int d=g->primFmt.dwRGBBitCount;d<=32;d+=8 ){
- for( int k=0;k<tex_fmts.size();++k ){
- const TexFmt &t=tex_fmts[k];
- if( !t.a_bits || !t.rgb_bits || t.rgb_bits<max ) continue;
- if( t.rgb_bits==max && t.bits>=bits ) continue;
- pick=k;max=t.rgb_bits;bits=t.bits;
- }
- if( !hi && pick>=0 ) break;
- }
- if( pick<0 ) g->texRGBMaskFmt[hi]=g->primFmt;
- else g->texRGBMaskFmt[hi]=tex_fmts[pick].fmt;
- }
- }
- gxScene *gxGraphics::createScene( int flags ){
- if( scene_set.size() ) return 0;
- //get d3d
- if( dirDraw->QueryInterface( IID_IDirect3D7,(void**)&dir3d )>=0 ){
- //enum devices
- maxDevType=0;
- if( dir3d->EnumDevices( enumDevice,this )>=0 && maxDevType>1 ){
- //enum zbuffer formats
- zbuffFmt.dwZBufferBitDepth=0;
- if( dir3d->EnumZBufferFormats( dir3dDevDesc.deviceGUID,enumZbuffFormat,this )>=0 ){
- //create zbuff for back buffer
- if( back_canvas->attachZBuffer() ){
- //create 3d device
- if( dir3d->CreateDevice( dir3dDevDesc.deviceGUID,back_canvas->getSurface(),&dir3dDev )>=0 ){
- //enum texture formats
- tex_fmts.clear();
- if( dir3dDev->EnumTextureFormats( enumTextureFormat,this )>=0 ){
- pickTexFmts( this,0 );
- pickTexFmts( this,1 );
- tex_fmts.clear();
- #ifdef BETA
- gx_runtime->debugLog( "Texture RGB format:" );
- debugPF( texRGBFmt );
- gx_runtime->debugLog( "Texture Alpha format:" );
- debugPF( texAlphaFmt );
- gx_runtime->debugLog( "Texture RGB Alpha format:" );
- debugPF( texRGBAlphaFmt );
- gx_runtime->debugLog( "Texture RGB Mask format:" );
- debugPF( texRGBMaskFmt );
- gx_runtime->debugLog( "Texture Primary format:" );
- debugPF( primFmt );
- string ts="ZBuffer Bit Depth:"+itoa( zbuffFmt.dwZBufferBitDepth );
- gx_runtime->debugLog( ts.c_str() );
- #endif
- gxScene *scene=d_new gxScene( this,back_canvas );
- scene_set.insert( scene );
- dummy_mesh=createMesh( 8,12,0 );
- return scene;
- }
- dir3dDev->Release();
- dir3dDev=0;
- }
- back_canvas->releaseZBuffer();
- }
- }
- }
- dir3d->Release();
- dir3d=0;
- }
- return 0;
- }
- gxScene *gxGraphics::verifyScene( gxScene *s ){
- return scene_set.count( s ) ? s : 0;
- }
- void gxGraphics::freeScene( gxScene *scene ){
- if( !scene_set.erase( scene ) ) return;
- dummy_mesh=0;
- while( mesh_set.size() ) freeMesh( *mesh_set.begin() );
- back_canvas->releaseZBuffer();
- if( dir3dDev ){ dir3dDev->Release();dir3dDev=0; }
- if( dir3d ){ dir3d->Release();dir3d=0; }
- delete scene;
- }
- gxMesh *gxGraphics::createMesh( int max_verts,int max_tris,int flags ){
- static const int VTXFMT=
- D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_DIFFUSE|D3DFVF_TEX2|
- D3DFVF_TEXCOORDSIZE2(0)|D3DFVF_TEXCOORDSIZE2(1);
- int vbflags=0;
- //XP or less?
- if( runtime->osinfo.dwMajorVersion<6 ){
- vbflags|=D3DVBCAPS_WRITEONLY;
- }
- D3DVERTEXBUFFERDESC desc={ sizeof(desc),vbflags,VTXFMT,max_verts };
- IDirect3DVertexBuffer7 *buff;
- if( dir3d->CreateVertexBuffer( &desc,&buff,0 )<0 ) return 0;
- WORD *indices=d_new WORD[max_tris*3];
- gxMesh *mesh=d_new gxMesh( this,buff,indices,max_verts,max_tris );
- mesh_set.insert( mesh );
- return mesh;
- }
- gxMesh *gxGraphics::verifyMesh( gxMesh *m ){
- return mesh_set.count( m ) ? m : 0;
- }
- void gxGraphics::freeMesh( gxMesh *mesh ){
- if( mesh_set.erase( mesh ) ) delete mesh;
- }
- #endif
|