/* ** Haaf's Game Engine 1.8 ** Copyright (C) 2003-2007, Relish Games ** hge.relishgames.com ** ** Core functions implementation: graphics ** Upgraded to DirectX9 By Chris Xiong, 2013/08/08 */ #include "hge_impl.h" #include #include static const char* GRAPHICS_SRC_FN="hge/graphics.cpp"; void CALL HGE_Impl::Gfx_Clear(DWORD color) { if(pCurTarget) { if(pCurTarget->pDepth) pD3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, color, 1.0f, 0 ); else pD3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET, color, 1.0f, 0 ); } else { if(bZBuffer) pD3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, color, 1.0f, 0 ); else pD3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET, color, 1.0f, 0 ); } } void CALL HGE_Impl::Gfx_SetClipping(int x, int y, int w, int h) { D3DVIEWPORT9 vp; int scr_width, scr_height; if(!pCurTarget) { scr_width=pHGE->System_GetStateInt(HGE_SCREENWIDTH); scr_height=pHGE->System_GetStateInt(HGE_SCREENHEIGHT); } else { scr_width=Texture_GetWidth((HTEXTURE)pCurTarget->pTex); scr_height=Texture_GetHeight((HTEXTURE)pCurTarget->pTex); } if(!w) { vp.X=0; vp.Y=0; vp.Width=scr_width; vp.Height=scr_height; } else { if(x<0) { w+=x; x=0; } if(y<0) { h+=y; y=0; } if(x+w > scr_width) w=scr_width-x; if(y+h > scr_height) h=scr_height-y; vp.X=x; vp.Y=y; vp.Width=w; vp.Height=h; } vp.MinZ=0.0f; vp.MaxZ=1.0f; _render_batch(); pD3DDevice->SetViewport(&vp); D3DXMATRIX tmp; D3DXMatrixScaling(&matProj, 1.0f, -1.0f, 1.0f); D3DXMatrixTranslation(&tmp, -0.5f, +0.5f, 0.0f); D3DXMatrixMultiply(&matProj, &matProj, &tmp); D3DXMatrixOrthoOffCenterLH(&tmp, (float)vp.X, (float)(vp.X+vp.Width), -((float)(vp.Y+vp.Height)), -((float)vp.Y), vp.MinZ, vp.MaxZ); D3DXMatrixMultiply(&matProj, &matProj, &tmp); pD3DDevice->SetTransform(D3DTS_PROJECTION, &matProj); } void CALL HGE_Impl::Gfx_SetTransform(float x, float y, float dx, float dy, float rot, float hscale, float vscale) { D3DXMATRIX tmp; if(vscale==0.0f) D3DXMatrixIdentity(&matView); else { D3DXMatrixTranslation(&matView, -x, -y, 0.0f); D3DXMatrixScaling(&tmp, hscale, vscale, 1.0f); D3DXMatrixMultiply(&matView, &matView, &tmp); D3DXMatrixRotationZ(&tmp, -rot); D3DXMatrixMultiply(&matView, &matView, &tmp); D3DXMatrixTranslation(&tmp, x+dx, y+dy, 0.0f); D3DXMatrixMultiply(&matView, &matView, &tmp); } _render_batch(); pD3DDevice->SetTransform(D3DTS_VIEW, &matView); } bool CALL HGE_Impl::Gfx_BeginScene(HTARGET targ) { LPDIRECT3DSURFACE9 pSurf=0, pDepth=0; D3DDISPLAYMODE Mode; CRenderTargetList *target=(CRenderTargetList *)targ; HRESULT hr = pD3DDevice->TestCooperativeLevel(); if (hr == D3DERR_DEVICELOST) return false; else if (hr == D3DERR_DEVICENOTRESET) { if(bWindowed) { if(FAILED(pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &Mode)) || Mode.Format==D3DFMT_UNKNOWN) { _PostError("Can't determine desktop video mode"); return false; } d3dppW.BackBufferFormat = Mode.Format; if(_format_id(Mode.Format) < 4) nScreenBPP=16; else nScreenBPP=32; } if(!_GfxRestore()) return false; } if(VertArray) { _PostError("Gfx_BeginScene: Scene is already being rendered"); return false; } if(target != pCurTarget) { if(target) { target->pTex->GetSurfaceLevel(0, &pSurf); pDepth=target->pDepth; } else { pSurf=pScreenSurf; pDepth=pScreenDepth; } if(FAILED(pD3DDevice->SetRenderTarget(0,pSurf))) { if(target) pSurf->Release(); _PostError("Gfx_BeginScene: Can't set render target"); return false; } if(target) { pSurf->Release(); if(target->pDepth) pD3DDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE ); else pD3DDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE ); _SetProjectionMatrix(target->width, target->height); } else { if(bZBuffer) pD3DDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE ); else pD3DDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE ); _SetProjectionMatrix(nScreenWidth, nScreenHeight); } pD3DDevice->SetTransform(D3DTS_PROJECTION, &matProj); D3DXMatrixIdentity(&matView); pD3DDevice->SetTransform(D3DTS_VIEW, &matView); pCurTarget=target; } pD3DDevice->BeginScene(); pVB->Lock( 0, 0, (VOID**)&VertArray, 0 ); return true; } void CALL HGE_Impl::Gfx_EndScene() { _render_batch(true); pD3DDevice->EndScene(); if(!pCurTarget) pD3DDevice->Present( NULL, NULL, NULL, NULL ); } void CALL HGE_Impl::Gfx_RenderLine(float x1, float y1, float x2, float y2, DWORD color, float z) { if(VertArray) { if(CurPrimType!=HGEPRIM_LINES || nPrim>=VERTEX_BUFFER_SIZE/HGEPRIM_LINES || CurTexture || CurBlendMode!=BLEND_DEFAULT) { _render_batch(); CurPrimType=HGEPRIM_LINES; if(CurBlendMode != BLEND_DEFAULT) _SetBlendMode(BLEND_DEFAULT); if(CurTexture) { pD3DDevice->SetTexture(0, 0); CurTexture=0; } } int i=nPrim*HGEPRIM_LINES; VertArray[i].x = x1; VertArray[i+1].x = x2; VertArray[i].y = y1; VertArray[i+1].y = y2; VertArray[i].z = VertArray[i+1].z = z; VertArray[i].col = VertArray[i+1].col = color; VertArray[i].tx = VertArray[i+1].tx = VertArray[i].ty = VertArray[i+1].ty = 0.0f; nPrim++; } } void CALL HGE_Impl::Gfx_RenderTriple(const hgeTriple *triple) { if(VertArray) { if(CurPrimType!=HGEPRIM_TRIPLES || nPrim>=VERTEX_BUFFER_SIZE/HGEPRIM_TRIPLES || CurTexture!=triple->tex || CurBlendMode!=triple->blend) { _render_batch(); CurPrimType=HGEPRIM_TRIPLES; if(CurBlendMode != triple->blend) _SetBlendMode(triple->blend); if(triple->tex != CurTexture) { pD3DDevice->SetTexture( 0, (LPDIRECT3DTEXTURE9)triple->tex ); CurTexture = triple->tex; } } memcpy(&VertArray[nPrim*HGEPRIM_TRIPLES], triple->v, sizeof(hgeVertex)*HGEPRIM_TRIPLES); nPrim++; } } void CALL HGE_Impl::Gfx_RenderQuad(const hgeQuad *quad) { if(VertArray) { if(CurPrimType!=HGEPRIM_QUADS || nPrim>=VERTEX_BUFFER_SIZE/HGEPRIM_QUADS || CurTexture!=quad->tex || CurBlendMode!=quad->blend) { _render_batch(); CurPrimType=HGEPRIM_QUADS; if(CurBlendMode != quad->blend) _SetBlendMode(quad->blend); if(quad->tex != CurTexture) { pD3DDevice->SetTexture( 0, (LPDIRECT3DTEXTURE9)quad->tex ); CurTexture = quad->tex; } } memcpy(&VertArray[nPrim*HGEPRIM_QUADS], quad->v, sizeof(hgeVertex)*HGEPRIM_QUADS); nPrim++; } } hgeVertex* CALL HGE_Impl::Gfx_StartBatch(int prim_type, HTEXTURE tex, int blend, int *max_prim) { if(VertArray) { _render_batch(); CurPrimType=prim_type; if(CurBlendMode != blend) _SetBlendMode(blend); if(tex != CurTexture) { pD3DDevice->SetTexture( 0, (LPDIRECT3DTEXTURE9)tex ); CurTexture = tex; } *max_prim=VERTEX_BUFFER_SIZE / prim_type; return VertArray; } else return 0; } void CALL HGE_Impl::Gfx_FinishBatch(int nprim) { nPrim=nprim; } HTARGET CALL HGE_Impl::Target_Create(int width, int height, bool zbuffer) { CRenderTargetList *pTarget; D3DSURFACE_DESC TDesc; pTarget = new CRenderTargetList; pTarget->pTex=0; pTarget->pDepth=0; if(FAILED(D3DXCreateTexture(pD3DDevice, width, height, 1, D3DUSAGE_RENDERTARGET, d3dpp->BackBufferFormat, D3DPOOL_DEFAULT, &pTarget->pTex))) { _PostError("Can't create render target texture"); delete pTarget; return 0; } pTarget->pTex->GetLevelDesc(0, &TDesc); pTarget->width=TDesc.Width; pTarget->height=TDesc.Height; if(zbuffer) { if(FAILED(pD3DDevice->CreateDepthStencilSurface(width, height, D3DFMT_D16, D3DMULTISAMPLE_NONE, 0, false, &pTarget->pDepth, NULL))) { pTarget->pTex->Release(); _PostError("Can't create render target depth buffer"); delete pTarget; return 0; } } pTarget->next=pTargets; pTargets=pTarget; return (HTARGET)pTarget; } void CALL HGE_Impl::Target_Free(HTARGET target) { CRenderTargetList *pTarget=pTargets, *pPrevTarget=NULL; while(pTarget) { if((CRenderTargetList *)target == pTarget) { if(pPrevTarget) pPrevTarget->next = pTarget->next; else pTargets = pTarget->next; if(pTarget->pTex) pTarget->pTex->Release(); if(pTarget->pDepth) pTarget->pDepth->Release(); delete pTarget; return; } pPrevTarget = pTarget; pTarget = pTarget->next; } } HTEXTURE CALL HGE_Impl::Target_GetTexture(HTARGET target) { CRenderTargetList *targ=(CRenderTargetList *)target; if(target) return (HTEXTURE)targ->pTex; else return 0; } HTEXTURE CALL HGE_Impl::Texture_Create(int width, int height) { LPDIRECT3DTEXTURE9 pTex; if( FAILED( D3DXCreateTexture( pD3DDevice, width, height, 1, // Mip levels 0, // Usage D3DFMT_A8R8G8B8, // Format D3DPOOL_MANAGED, // Memory pool &pTex ) ) ) { _PostError("Can't create texture"); return NULL; } return (HTEXTURE)pTex; } HTEXTURE CALL HGE_Impl::Texture_Load(const char *filename, DWORD size, bool bMipmap) { void *data; DWORD _size; D3DFORMAT fmt1, fmt2; LPDIRECT3DTEXTURE9 pTex; D3DXIMAGE_INFO info; CTextureList *texItem; if(size) { data=(void *)filename; _size=size; } else { data=pHGE->Resource_Load(filename, &_size); if(!data) return NULL; } if(*(DWORD*)data == 0x20534444) // Compressed DDS format magic number { fmt1=D3DFMT_UNKNOWN; fmt2=D3DFMT_A8R8G8B8; } else { fmt1=D3DFMT_A8R8G8B8; fmt2=D3DFMT_UNKNOWN; } // if( FAILED( D3DXCreateTextureFromFileInMemory( pD3DDevice, data, _size, &pTex ) ) ) pTex=NULL; if( FAILED( D3DXCreateTextureFromFileInMemoryEx( pD3DDevice, data, _size, D3DX_DEFAULT, D3DX_DEFAULT, bMipmap ? 0:1, // Mip levels 0, // Usage fmt1, // Format D3DPOOL_MANAGED, // Memory pool D3DX_FILTER_NONE, // Filter D3DX_DEFAULT, // Mip filter 0, // Color key &info, NULL, &pTex ) ) ) if( FAILED( D3DXCreateTextureFromFileInMemoryEx( pD3DDevice, data, _size, D3DX_DEFAULT, D3DX_DEFAULT, bMipmap ? 0:1, // Mip levels 0, // Usage fmt2, // Format D3DPOOL_MANAGED, // Memory pool D3DX_FILTER_NONE, // Filter D3DX_DEFAULT, // Mip filter 0, // Color key &info, NULL, &pTex ) ) ) { _PostError("Can't create texture"); if(!size) Resource_Free(data); return NULL; } if(!size) Resource_Free(data); texItem=new CTextureList; texItem->tex=(HTEXTURE)pTex; texItem->width=info.Width; texItem->height=info.Height; texItem->next=textures; textures=texItem; return (HTEXTURE)pTex; } void CALL HGE_Impl::Texture_Free(HTEXTURE tex) { LPDIRECT3DTEXTURE9 pTex=(LPDIRECT3DTEXTURE9)tex; CTextureList *texItem=textures, *texPrev=0; while(texItem) { if(texItem->tex==tex) { if(texPrev) texPrev->next=texItem->next; else textures=texItem->next; delete texItem; break; } texPrev=texItem; texItem=texItem->next; } if(pTex != NULL) pTex->Release(); } int CALL HGE_Impl::Texture_GetWidth(HTEXTURE tex, bool bOriginal) { D3DSURFACE_DESC TDesc; LPDIRECT3DTEXTURE9 pTex=(LPDIRECT3DTEXTURE9)tex; CTextureList *texItem=textures; if(bOriginal) { while(texItem) { if(texItem->tex==tex) return texItem->width; texItem=texItem->next; } return 0; } else { if(FAILED(pTex->GetLevelDesc(0, &TDesc))) return 0; else return TDesc.Width; } } int CALL HGE_Impl::Texture_GetHeight(HTEXTURE tex, bool bOriginal) { D3DSURFACE_DESC TDesc; LPDIRECT3DTEXTURE9 pTex=(LPDIRECT3DTEXTURE9)tex; CTextureList *texItem=textures; if(bOriginal) { while(texItem) { if(texItem->tex==tex) return texItem->height; texItem=texItem->next; } return 0; } else { if(FAILED(pTex->GetLevelDesc(0, &TDesc))) return 0; else return TDesc.Height; } } DWORD * CALL HGE_Impl::Texture_Lock(HTEXTURE tex, bool bReadOnly, int left, int top, int width, int height) { LPDIRECT3DTEXTURE9 pTex=(LPDIRECT3DTEXTURE9)tex; D3DSURFACE_DESC TDesc; D3DLOCKED_RECT TRect; RECT region, *prec; int flags; pTex->GetLevelDesc(0, &TDesc); if(TDesc.Format!=D3DFMT_A8R8G8B8 && TDesc.Format!=D3DFMT_X8R8G8B8) return 0; if(width && height) { region.left=left; region.top=top; region.right=left+width; region.bottom=top+height; prec=®ion; } else prec=0; if(bReadOnly) flags=D3DLOCK_READONLY; else flags=0; if(FAILED(pTex->LockRect(0, &TRect, prec, flags))) { _PostError("Can't lock texture"); return 0; } return (DWORD *)TRect.pBits; } void CALL HGE_Impl::Texture_Unlock(HTEXTURE tex) { LPDIRECT3DTEXTURE9 pTex=(LPDIRECT3DTEXTURE9)tex; pTex->UnlockRect(0); } //////// Implementation //////// void HGE_Impl::_render_batch(bool bEndScene) { if(VertArray) { pVB->Unlock(); if(nPrim) { switch(CurPrimType) { case HGEPRIM_QUADS: pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, nPrim<<2, 0, nPrim<<1); break; case HGEPRIM_TRIPLES: pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, nPrim); break; case HGEPRIM_LINES: pD3DDevice->DrawPrimitive(D3DPT_LINELIST, 0, nPrim); break; } nPrim=0; } if(bEndScene) VertArray = 0; else pVB->Lock( 0, 0, (VOID**)&VertArray, 0 ); } } void HGE_Impl::_SetBlendMode(int blend) { if((blend & BLEND_ALPHABLEND) != (CurBlendMode & BLEND_ALPHABLEND)) { if(blend & BLEND_ALPHABLEND) pD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); else pD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); } if((blend & BLEND_ZWRITE) != (CurBlendMode & BLEND_ZWRITE)) { if(blend & BLEND_ZWRITE) pD3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE); else pD3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); } if((blend & BLEND_COLORADD) != (CurBlendMode & BLEND_COLORADD)) { if(blend & BLEND_COLORADD) pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_ADD); else pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); } CurBlendMode = blend; } void HGE_Impl::_SetProjectionMatrix(int width, int height) { D3DXMATRIX tmp; D3DXMatrixScaling(&matProj, 1.0f, -1.0f, 1.0f); D3DXMatrixTranslation(&tmp, -0.5f, height+0.5f, 0.0f); D3DXMatrixMultiply(&matProj, &matProj, &tmp); D3DXMatrixOrthoOffCenterLH(&tmp, 0, (float)width, 0, (float)height, 0.0f, 1.0f); D3DXMatrixMultiply(&matProj, &matProj, &tmp); } bool HGE_Impl::_GfxInit() { static const char *szFormats[]={"UNKNOWN", "R5G6B5", "X1R5G5B5", "A1R5G5B5", "X8R8G8B8", "A8R8G8B8"}; D3DADAPTER_IDENTIFIER9 AdID; D3DDISPLAYMODE Mode; D3DFORMAT Format=D3DFMT_UNKNOWN; UINT nModes, i; // Init D3D pD3D=Direct3DCreate9(D3D_SDK_VERSION); // D3D_SDK_VERSION if(pD3D==NULL) { _PostError("Can't create D3D interface"); return false; } // Get adapter info pD3D->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &AdID); System_Log("%s: D3D Driver: %s",GRAPHICS_SRC_FN,AdID.Driver); System_Log("%s: Description: %s",GRAPHICS_SRC_FN,AdID.Description); System_Log("%s: Version: %d.%d.%d.%d", GRAPHICS_SRC_FN, HIWORD(AdID.DriverVersion.HighPart), LOWORD(AdID.DriverVersion.HighPart), HIWORD(AdID.DriverVersion.LowPart), LOWORD(AdID.DriverVersion.LowPart)); // Set up Windowed presentation parameters if(FAILED(pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &Mode)) || Mode.Format==D3DFMT_UNKNOWN) { _PostError("Can't determine desktop video mode"); if(bWindowed) return false; } ZeroMemory(&d3dppW, sizeof(d3dppW)); d3dppW.BackBufferWidth = nScreenWidth; d3dppW.BackBufferHeight = nScreenHeight; d3dppW.BackBufferFormat = Mode.Format; d3dppW.BackBufferCount = 1; d3dppW.MultiSampleType = D3DMULTISAMPLE_NONE; d3dppW.hDeviceWindow = hwnd; d3dppW.Windowed = TRUE; if(nHGEFPS==HGEFPS_VSYNC) { d3dppW.SwapEffect = D3DSWAPEFFECT_COPY; d3dppW.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; } else { d3dppW.SwapEffect = D3DSWAPEFFECT_COPY; d3dppW.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;} if(bZBuffer) { d3dppW.EnableAutoDepthStencil = TRUE; d3dppW.AutoDepthStencilFormat = D3DFMT_D16; } // Set up Full Screen presentation parameters nModes=pD3D->GetAdapterModeCount(D3DADAPTER_DEFAULT, Mode.Format); for(i=0; iEnumAdapterModes(D3DADAPTER_DEFAULT, Mode.Format, i, &Mode); if(Mode.Width != (UINT)nScreenWidth || Mode.Height != (UINT)nScreenHeight) continue; if(nScreenBPP==16 && (_format_id(Mode.Format) > _format_id(D3DFMT_A1R5G5B5))) continue; if(_format_id(Mode.Format) > _format_id(Format)) Format=Mode.Format; } if(Format == D3DFMT_UNKNOWN) { _PostError("Can't find appropriate full screen video mode"); if(!bWindowed) return false; } ZeroMemory(&d3dppFS, sizeof(d3dppFS)); d3dppFS.BackBufferWidth = nScreenWidth; d3dppFS.BackBufferHeight = nScreenHeight; d3dppFS.BackBufferFormat = Format; d3dppFS.BackBufferCount = 1; d3dppFS.MultiSampleType = D3DMULTISAMPLE_NONE; d3dppFS.hDeviceWindow = hwnd; d3dppFS.Windowed = FALSE; d3dppFS.SwapEffect = D3DSWAPEFFECT_FLIP; d3dppFS.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; if(nHGEFPS==HGEFPS_VSYNC) d3dppFS.PresentationInterval = D3DPRESENT_INTERVAL_ONE; else d3dppFS.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; if(bZBuffer) { d3dppFS.EnableAutoDepthStencil = TRUE; d3dppFS.AutoDepthStencilFormat = D3DFMT_D16; } d3dpp = bWindowed ? &d3dppW : &d3dppFS; if(_format_id(d3dpp->BackBufferFormat) < 4) nScreenBPP=16; else nScreenBPP=32; // Create D3D Device if( FAILED( pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, d3dpp, &pD3DDevice ) ) ) { _PostError("Can't create D3D device"); return false; } _AdjustWindow(); System_Log("%s: Mode: %d x %d x %s\n",GRAPHICS_SRC_FN,nScreenWidth,nScreenHeight,szFormats[_format_id(Format)]); // Create vertex batch buffer VertArray=0; textures=0; // Init all stuff that can be lost _SetProjectionMatrix(nScreenWidth, nScreenHeight); D3DXMatrixIdentity(&matView); if(!_init_lost()) return false; Gfx_Clear(0); return true; } int HGE_Impl::_format_id(D3DFORMAT fmt) { switch(fmt) { case D3DFMT_R5G6B5: return 1; case D3DFMT_X1R5G5B5: return 2; case D3DFMT_A1R5G5B5: return 3; case D3DFMT_X8R8G8B8: return 4; case D3DFMT_A8R8G8B8: return 5; default: return 0; } } void HGE_Impl::_AdjustWindow() { RECT *rc; LONG style; if(bWindowed) {rc=&rectW; style=styleW; } else {rc=&rectFS; style=styleFS; } SetWindowLong(hwnd, GWL_STYLE, style); style=GetWindowLong(hwnd, GWL_EXSTYLE); if(bWindowed) { SetWindowLong(hwnd, GWL_EXSTYLE, style & (~WS_EX_TOPMOST)); SetWindowPos(hwnd, HWND_NOTOPMOST, rc->left, rc->top, rc->right-rc->left, rc->bottom-rc->top, SWP_FRAMECHANGED); } else { SetWindowLong(hwnd, GWL_EXSTYLE, style | WS_EX_TOPMOST); SetWindowPos(hwnd, HWND_TOPMOST, rc->left, rc->top, rc->right-rc->left, rc->bottom-rc->top, SWP_FRAMECHANGED); } } void HGE_Impl::_Resize(int width, int height) { if(hwndParent) { //if(procFocusLostFunc) procFocusLostFunc(); d3dppW.BackBufferWidth=width; d3dppW.BackBufferHeight=height; nScreenWidth=width; nScreenHeight=height; _SetProjectionMatrix(nScreenWidth, nScreenHeight); _GfxRestore(); //if(procFocusGainFunc) procFocusGainFunc(); } } void HGE_Impl::_GfxDone() { CRenderTargetList *target=pTargets, *next_target; while(textures) Texture_Free(textures->tex); if(pScreenSurf) { pScreenSurf->Release(); pScreenSurf=0; } if(pScreenDepth) { pScreenDepth->Release(); pScreenDepth=0; } while(target) { if(target->pTex) target->pTex->Release(); if(target->pDepth) target->pDepth->Release(); next_target=target->next; delete target; target=next_target; } pTargets=0; if(pIB) { pD3DDevice->SetIndices(NULL); pIB->Release(); pIB=0; } if(pVB) { if(VertArray) { pVB->Unlock(); VertArray=0; } pD3DDevice->SetStreamSource( 0, NULL, 0, sizeof(hgeVertex) ); pVB->Release(); pVB=0; } if(pD3DDevice) { pD3DDevice->Release(); pD3DDevice=0; } if(pD3D) { pD3D->Release(); pD3D=0; } } bool HGE_Impl::_GfxRestore() { CRenderTargetList *target=pTargets; //if(!pD3DDevice) return false; //if(pD3DDevice->TestCooperativeLevel() == D3DERR_DEVICELOST) return; if(pScreenSurf) pScreenSurf->Release(); if(pScreenDepth) pScreenDepth->Release(); while(target) { if(target->pTex) target->pTex->Release(); if(target->pDepth) target->pDepth->Release(); target=target->next; } if(pIB) { pD3DDevice->SetIndices(NULL); pIB->Release(); } if(pVB) { pD3DDevice->SetStreamSource( 0, NULL, 0, sizeof(hgeVertex) ); pVB->Release(); } pD3DDevice->Reset(d3dpp); if(!_init_lost()) return false; if(procGfxRestoreFunc) return procGfxRestoreFunc(); return true; } bool HGE_Impl::_init_lost() { CRenderTargetList *target=pTargets; // Store render target pScreenSurf=0; pScreenDepth=0; pD3DDevice->GetRenderTarget(0, &pScreenSurf); pD3DDevice->GetDepthStencilSurface(&pScreenDepth); while(target) { if(target->pTex) D3DXCreateTexture(pD3DDevice, target->width, target->height, 1, D3DUSAGE_RENDERTARGET, d3dpp->BackBufferFormat, D3DPOOL_DEFAULT, &target->pTex); if(target->pDepth) pD3DDevice->CreateDepthStencilSurface(target->width, target->height, D3DFMT_D16, D3DMULTISAMPLE_NONE, 0, false, &target->pDepth, NULL); target=target->next; } // Create Vertex buffer if( FAILED (pD3DDevice->CreateVertexBuffer(VERTEX_BUFFER_SIZE*sizeof(hgeVertex), D3DUSAGE_WRITEONLY, D3DFVF_HGEVERTEX, D3DPOOL_DEFAULT, &pVB, NULL))) { _PostError("Can't create D3D vertex buffer"); return false; } pD3DDevice->SetVertexShader( NULL ); pD3DDevice->SetFVF( D3DFVF_HGEVERTEX ); pD3DDevice->SetStreamSource( 0, pVB, 0, sizeof(hgeVertex) ); // Create and setup Index buffer if( FAILED( pD3DDevice->CreateIndexBuffer(VERTEX_BUFFER_SIZE*6/4*sizeof(WORD), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &pIB, NULL))) { _PostError("Can't create D3D index buffer"); return false; } WORD *pIndices, n=0; if( FAILED( pIB->Lock( 0, 0, (VOID**)&pIndices, 0 ) ) ) { _PostError("Can't lock D3D index buffer"); return false; } for(int i=0; iUnlock(); pD3DDevice->SetIndices(pIB); // Set common render states //pD3DDevice->SetRenderState( D3DRS_LASTPIXEL, FALSE ); pD3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); pD3DDevice->SetRenderState( D3DRS_LIGHTING, FALSE ); pD3DDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE ); pD3DDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA ); pD3DDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA ); pD3DDevice->SetRenderState( D3DRS_ALPHATESTENABLE, TRUE ); pD3DDevice->SetRenderState( D3DRS_ALPHAREF, 0x01 ); pD3DDevice->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL ); pD3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE ); pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); pD3DDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT); if(bTextureFilter) { pD3DDevice->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR); pD3DDevice->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR); } else { pD3DDevice->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_POINT); pD3DDevice->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_POINT); } nPrim=0; CurPrimType=HGEPRIM_QUADS; CurBlendMode = BLEND_DEFAULT; CurTexture = NULL; pD3DDevice->SetTransform(D3DTS_VIEW, &matView); pD3DDevice->SetTransform(D3DTS_PROJECTION, &matProj); return true; }