00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "CATOverlayDirect3D9.h"
00014 #include "CATString.h"
00015
00016 #ifdef CAT_CONFIG_WIN32
00017 #include <d3d9.h>
00018
00019
00020
00021 CATINTERCEPT_COM_TABLE_ENTRY CATOverlayDirect3D9::kDirect3DDeviceInterceptTable9[] =
00022 {
00023
00024 { 16, CATOverlayDirect3D9::OnReset9, 5},
00025 { 17, CATOverlayDirect3D9::OnPresent9, 5},
00026 { 42, CATOverlayDirect3D9::OnEndScene, 5},
00027
00028 {(CATUInt32)-1,0,-1}
00029 };
00030 CATOverlayDirect3D9::CATOverlayDirect3D9()
00031 {
00032 fDeviceLost = true;
00033 fTexture = 0;
00034 fBackTexture = 0;
00035 fTexScaleX = 1.0f;
00036 fTexScaleY = 1.0f;
00037 fD3d9DLL = ::LoadLibrary(L"d3d9.dll");
00038 }
00039
00040 CATOverlayDirect3D9::~CATOverlayDirect3D9()
00041 {
00042 RestoreAll();
00043 if (fD3d9DLL)
00044 FreeLibrary(fD3d9DLL);
00045 fD3d9DLL = 0;
00046 }
00047
00048 void CATOverlayDirect3D9::DrawToScene(IDirect3DDevice9* device)
00049 {
00050 fLock.Wait();
00051
00052 if (fDeviceLost)
00053 {
00054 fLock.Release();
00055 return;
00056 }
00057
00058
00059 if (fOverlayDirty)
00060 {
00061
00062 if (fTexture)
00063 fTexture->Release();
00064 if (fBackTexture)
00065 fBackTexture->Release();
00066
00067 fTexture = 0;
00068 fBackTexture = 0;
00069
00070 if (fOverlay == 0)
00071 {
00072 fLock.Release();
00073 return;
00074 }
00075
00076 CATInt32 tw = 2;
00077 while (tw < fOverlay->Width())
00078 tw*= 2;
00079 CATInt32 th = 2;
00080 while (th < fOverlay->Height())
00081 th*=2;
00082
00083 RECT textureRect;
00084 textureRect.left = textureRect.top = 0;
00085 textureRect.right = tw;
00086 textureRect.bottom = th;
00087
00088 HRESULT hr = device->CreateTexture(tw,th,1,0,D3DFMT_A8R8G8B8,D3DPOOL_DEFAULT,&fBackTexture,0);
00089 hr |= device->CreateTexture(tw,th,1,0,D3DFMT_A8R8G8B8,D3DPOOL_SYSTEMMEM,&fTexture,0);
00090
00091 if (FAILED(hr))
00092 {
00093 ::OutputDebugString(L"Failed creating texture");
00094 fLock.Release();
00095 return;
00096 }
00097
00098 D3DSURFACE_DESC surfaceDesc,sd2;
00099 fTexture->GetLevelDesc(0,&surfaceDesc);
00100 fBackTexture->GetLevelDesc(0,&sd2);
00101 if ((surfaceDesc.Format != D3DFMT_A8R8G8B8) || (sd2.Format != D3DFMT_A8R8G8B8))
00102 {
00103 CATString dbg;
00104 dbg.Format(L"Surface format mismatch. %d",surfaceDesc.Format);
00105 ::OutputDebugString(dbg);
00106 fTexture->Release();
00107 fTexture = 0;
00108 fBackTexture->Release();
00109 fBackTexture = 0;
00110 fLock.Release();
00111 return;
00112 }
00113
00114 D3DLOCKED_RECT lockedRect;
00115 if (!FAILED(fTexture->LockRect(0,&lockedRect,&textureRect,0)))
00116 {
00117
00118 CATUInt8* buffer = (CATUInt8*)lockedRect.pBits;
00119 CATUInt8* srcBuf = fOverlay->GetRawDataPtr();
00120 CATUInt32 imgWidth = fOverlay->Width();
00121
00122
00123
00124 int uh = fOverlay->Height();
00125 int uw = fOverlay->Width();
00126
00127 memset(buffer,0,tw*th*4);
00128
00129 int dstLinePad = (tw - uw)*4;
00130 for (int y = 0; y < uh; y++)
00131 {
00132 for (int x = 0; x < uw; x++)
00133 {
00134 *buffer = srcBuf[2];
00135 buffer[2] = *srcBuf;
00136 buffer[1] = srcBuf[1];
00137 buffer[3] = srcBuf[3];
00138 buffer += 4;
00139 srcBuf += 4;
00140 }
00141 buffer += dstLinePad;
00142 }
00143 fTexture->UnlockRect(0);
00144
00145
00146 fTexScaleX = (CATFloat32)fOverlay->Width() / (CATFloat32)tw;
00147 fTexScaleY = (CATFloat32)fOverlay->Height() / (CATFloat32)th;
00148
00149 RECT textureRect;
00150 textureRect.left = textureRect.top = 0;
00151 textureRect.right = tw;
00152 textureRect.bottom = th;
00153
00154 device->UpdateTexture(fTexture, fBackTexture);
00155
00156 fOverlayDirty = false;
00157 }
00158 else
00159 {
00160 ::OutputDebugString(L"Failed to lock texture.");
00161 }
00162 }
00163
00164
00165 if (fBackTexture)
00166 {
00167 IDirect3DSurface9* surface = 0;
00168
00169 device->GetBackBuffer(0,0,D3DBACKBUFFER_TYPE_MONO,&surface);
00170 if (surface)
00171 {
00172 IDirect3DSurface9* textSurface = 0;
00173 fBackTexture->GetSurfaceLevel(0,&textSurface);
00174 if (textSurface)
00175 {
00176 RECT srcRect;
00177 srcRect.left = srcRect.top = 0;
00178 srcRect.bottom = fOverlay->Height();
00179
00180 srcRect.right = fOverlay->Width();
00181
00182 D3DSURFACE_DESC desc;
00183 surface->GetDesc(&desc);
00184
00185 POINT topLeft = {0.0};
00186 RECT destRect;
00187 fRect.right = desc.Width;
00188 fRect.bottom = desc.Height;
00189
00190 CATFloat32 scaleX = (CATFloat32)desc.Width / (CATFloat32)fRefScreenWidth;
00191 CATFloat32 scaleY = (CATFloat32)desc.Height / (CATFloat32)fRefScreenHeight;
00192 if (fKeepAspect)
00193 {
00194 scaleY = scaleX = CATMin(scaleX,scaleY);
00195 }
00196
00197 destRect.left = fOverlayRect.left*scaleX;
00198 destRect.top = fOverlayRect.top*scaleY;
00199 destRect.right = fOverlayRect.right*scaleX;
00200 destRect.bottom = fOverlayRect.bottom*scaleY;
00201
00202 HRESULT hr = device->StretchRect(textSurface,&srcRect,surface,&destRect,D3DTEXF_NONE);
00203 if (FAILED(hr))
00204 {
00205 CATString dbg;
00206
00207 surface->GetDesc(&desc);
00208 dbg.Format(L"Stretch failed: %08x Surface format: %d src %d,%d,%d,%d dst %d,%d,%d,%d",hr,desc.Format,
00209 srcRect.left, srcRect.top, srcRect.right, srcRect.bottom, destRect.left, destRect.top,destRect.right,destRect.bottom);
00210 ::OutputDebugString(dbg);
00211 dbg.Format(L"Target: %dx%d pool %d type %d Multi: %d MQ: %d",
00212 desc.Width, desc.Height, desc.Pool,desc.Type,desc.MultiSampleType, desc.MultiSampleQuality);
00213 ::OutputDebugString(dbg);
00214 }
00215 textSurface->Release();
00216 }
00217 else
00218 {
00219 ::OutputDebugString(L"didn't get texture surface..");
00220 }
00221
00222 surface->Release();
00223 }
00224 }
00225
00226 fLock.Release();
00227 }
00228
00229 void CATOverlayDirect3D9::Reset( IDirect3DDevice9* device,
00230 _D3DPRESENT_PARAMETERS_* presParams)
00231 {
00232 fLock.Wait();
00233 ::OutputDebugString(L"DX9: Reset");
00234
00235
00236 fDeviceLost = true;
00237
00238 if (fTexture)
00239 fTexture->Release();
00240 fTexture = 0;
00241 if (fBackTexture)
00242 fBackTexture->Release();
00243 fBackTexture = 0;
00244
00245 fLock.Release();
00246 }
00247
00248 void CATOverlayDirect3D9::DeviceLost( CATHOOK* hookInst,
00249 IDirect3DDevice9* device)
00250 {
00251
00252 CATOverlayDirect3D9* overlay = (CATOverlayDirect3D9*)hookInst->InterceptObj;
00253 overlay->fLock.Wait();
00254 ::OutputDebugString(L"DX9: Device Lost");
00255
00256 overlay->fDeviceLost = true;
00257
00258 if (overlay->fTexture)
00259 overlay->fTexture->Release();
00260 overlay->fTexture = 0;
00261 if (overlay->fBackTexture)
00262 overlay->fBackTexture->Release();
00263 overlay->fBackTexture = 0;
00264
00265 overlay->fLock.Release();
00266 }
00267
00268 void CATOverlayDirect3D9::DeviceOk( CATHOOK* hookInst,
00269 IDirect3DDevice9* device)
00270 {
00271
00272
00273 CATOverlayDirect3D9* overlay = (CATOverlayDirect3D9*)hookInst->InterceptObj;
00274 overlay->fLock.Wait();
00275
00276 if (overlay->fDeviceLost)
00277 {
00278 ::OutputDebugString(L"DX9: Device OK");
00279 overlay->fDeviceLost = false;
00280 overlay->fOverlayDirty = true;
00281 }
00282
00283 overlay->fLock.Release();
00284 }
00285
00286 CATResult CATOverlayDirect3D9::HookFunctions()
00287 {
00288 HWND procWnd = ::GetDesktopWindow();
00289
00290 HRESULT hr = 0;
00291
00292 CATResult result = CAT_SUCCESS;
00293
00294 D3DDISPLAYMODE displayMode;
00295 IDirect3D9* d3d9 = 0;
00296 IDirect3DDevice9* device9 = 0;
00297
00298
00299 result = this->LoadAndHook(L"Direct3DDevice9",kDirect3DDeviceInterceptTable9,this);
00300 if (CATSUCCEEDED(result))
00301 {
00302 return CAT_SUCCESS;
00303 }
00304 {
00305 typedef IDirect3D9* (STDMETHODCALLTYPE *DIRECT3DCREATE9FUNC)(UINT);
00306 DIRECT3DCREATE9FUNC d3dCreate9 = (DIRECT3DCREATE9FUNC)::GetProcAddress(fD3d9DLL,"Direct3DCreate9");
00307 if (d3dCreate9 == 0)
00308 {
00309 ::OutputDebugStringW(L"Failed to retrieve Direct3dCreate9 func.");
00310 return CATRESULT(CAT_ERR_INTERCEPT_NO_DSOUND);
00311 }
00312
00313 d3d9 = d3dCreate9(D3D_SDK_VERSION);
00314 if (d3d9 == 0)
00315 {
00316 ::OutputDebugStringW(L"Failed to create Direct3d9 object.");
00317 return CATRESULT(CAT_ERR_INTERCEPT_NO_DSOUND);
00318 }
00319
00320 hr = d3d9->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &displayMode );
00321 if (FAILED(hr))
00322 {
00323 ::OutputDebugStringW(L"Failed retrieving display mode.");
00324 return CATRESULT(CAT_ERR_INTERCEPT_NO_DSOUND);
00325 }
00326
00327 D3DPRESENT_PARAMETERS presentParams;
00328 memset(&presentParams, 0, sizeof(presentParams));
00329 presentParams.Windowed = true;
00330 presentParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
00331 presentParams.BackBufferFormat = displayMode.Format;
00332
00333
00334 hr = d3d9->CreateDevice( D3DADAPTER_DEFAULT,
00335 D3DDEVTYPE_HAL,
00336 procWnd,
00337 D3DCREATE_HARDWARE_VERTEXPROCESSING,
00338 &presentParams,
00339 &device9);
00340
00341 result = this->InterceptCOMObject(device9,kDirect3DDeviceInterceptTable9,this);
00342
00343
00344 if (CATSUCCEEDED(result))
00345 {
00346 SaveInterceptData(L"Direct3DDevice9",device9,kDirect3DDeviceInterceptTable9,this);
00347 }
00348
00349 if (device9)
00350 device9->Release();
00351
00352 if (d3d9)
00353 d3d9->Release();
00354 }
00355 return result;
00356 }
00357
00358
00359 CATHOOKFUNC void CATOverlayDirect3D9::OnReset9( CATHOOK* hookInst,
00360 IDirect3DDevice9* device,
00361 D3DPRESENT_PARAMETERS* presParams)
00362 {
00363 CATHOOK_PROLOGUE(2);
00364 CATHOOK_CALLORIGINAL_WINAPI(hookInst, 2);
00365 ((CATOverlayDirect3D9*)(hookInst->InterceptObj))->Reset(device,presParams);
00366 CATHOOK_EPILOGUE_WINAPI(2);
00367 }
00368
00369 CATHOOKFUNC void CATOverlayDirect3D9::OnPresent9( CATHOOK* hookInst,
00370 IDirect3DDevice9* device,
00371 const RECT* sourceRect,
00372 const RECT* destRect,
00373 HWND destWindow,
00374 const RGNDATA* pDirtyRgn)
00375 {
00376 CATHOOK_PROLOGUE(5);
00377 CATHOOK_CALLORIGINAL_WINAPI(hookInst, 5);
00378
00379 _asm
00380 {
00381 mov eax, [ebp-4]
00382 or eax, 0x80000000
00383 jnz presentOk
00384 push device
00385 push hookInst
00386 call DeviceLost
00387 add esp,8
00388 jmp presentDone
00389 presentOk:
00390 push device
00391 push hookInst
00392 call DeviceOk
00393 add esp,8
00394 presentDone:
00395 }
00396
00397 CATHOOK_EPILOGUE_WINAPI(5);
00398 }
00399
00400 CATHOOKFUNC void CATOverlayDirect3D9::OnEndScene( CATHOOK* hookInst,
00401 IDirect3DDevice9* device)
00402 {
00403 CATHOOK_PROLOGUE(1);
00404 ((CATOverlayDirect3D9*)(hookInst->InterceptObj))->DrawToScene(device);
00405 CATHOOK_CALLORIGINAL_WINAPI(hookInst, 1);
00406 CATHOOK_EPILOGUE_WINAPI(1);
00407 }
00408
00409 #endif // CAT_CONFIG_WIN32