aboutsummaryrefslogtreecommitdiff
path: root/archive/hgewin/graphics.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'archive/hgewin/graphics.cpp')
-rwxr-xr-xarchive/hgewin/graphics.cpp983
1 files changed, 983 insertions, 0 deletions
diff --git a/archive/hgewin/graphics.cpp b/archive/hgewin/graphics.cpp
new file mode 100755
index 0000000..43a5cc1
--- /dev/null
+++ b/archive/hgewin/graphics.cpp
@@ -0,0 +1,983 @@
+/*
+** 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 <d3d9.h>
+#include <d3dx9.h>
+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=&region;
+ }
+ 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; i<nModes; i++)
+ {
+ pD3D->EnumAdapterModes(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; i<VERTEX_BUFFER_SIZE/4; i++) {
+ *pIndices++=n;
+ *pIndices++=n+1;
+ *pIndices++=n+2;
+ *pIndices++=n+2;
+ *pIndices++=n+3;
+ *pIndices++=n;
+ n+=4;
+ }
+
+ pIB->Unlock();
+ 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;
+}