Significantly increased game capture logging data, added a variety of reacquiring fixes, fixed natural selection 2 not acquiring when windowed

This commit is contained in:
jp9000 2013-05-01 15:51:07 -07:00
parent e9df987b73
commit b07fe5526d
19 changed files with 727 additions and 118 deletions

View File

@ -77,6 +77,10 @@ void RefreshWindowList(HWND hwndCombobox, ConfigDialogData &configData)
RECT clientRect;
GetClientRect(hwndCurrent, &clientRect);
String strWindowName;
strWindowName.SetLength(GetWindowTextLength(hwndCurrent));
GetWindowText(hwndCurrent, strWindowName, strWindowName.Length()+1);
HWND hwndParent = GetParent(hwndCurrent);
DWORD exStyles = (DWORD)GetWindowLongPtr(hwndCurrent, GWL_EXSTYLE);
@ -84,9 +88,6 @@ void RefreshWindowList(HWND hwndCombobox, ConfigDialogData &configData)
if((exStyles & WS_EX_TOOLWINDOW) == 0 && (styles & WS_CHILD) == 0 /*&& hwndParent == NULL*/)
{
String strWindowName;
strWindowName.SetLength(GetWindowTextLength(hwndCurrent));
GetWindowText(hwndCurrent, strWindowName, strWindowName.Length()+1);
//-------

View File

@ -58,4 +58,5 @@ inline BOOL Is64BitWindows()
#include "MemoryCapture.h"
#include "SharedTexCapture.h"
#include "WindowCapture.h"
#include "GraphicsCaptureSource.h"

View File

@ -215,6 +215,7 @@
<ClCompile Include="GraphicsCaptureSource.cpp" />
<ClCompile Include="MemoryCapture.cpp" />
<ClCompile Include="SharedTexCapture.cpp" />
<ClCompile Include="WindowCapture.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="GlobalCaptureStuff.h" />
@ -223,6 +224,7 @@
<ClInclude Include="MemoryCapture.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="SharedTexCapture.h" />
<ClInclude Include="WindowCapture.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="GraphicsCapture.rc" />

View File

@ -27,6 +27,9 @@
<ClCompile Include="SharedTexCapture.cpp">
<Filter>Source</Filter>
</ClCompile>
<ClCompile Include="WindowCapture.cpp">
<Filter>Source</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="GlobalCaptureStuff.h">
@ -47,6 +50,9 @@
<ClInclude Include="SharedTexCapture.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="WindowCapture.h">
<Filter>Headers</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="GraphicsCapture.rc">

View File

@ -51,6 +51,9 @@ void ClearD3D101Data()
DestroySharedMemory();
keepAliveTime = 0;
resetCount++;
logOutput << "---------------------- Cleared D3D10.1 Capture ----------------------" << endl;
}
void SetupD3D101(IDXGISwapChain *swapChain)
@ -63,15 +66,20 @@ void SetupD3D101(IDXGISwapChain *swapChain)
d3d101CaptureInfo.format = ConvertGIBackBufferFormat(scd.BufferDesc.Format);
if(d3d101CaptureInfo.format != GS_UNKNOWNFORMAT)
{
if( dxgiFormat != scd.BufferDesc.Format ||
d3d101CaptureInfo.cx != scd.BufferDesc.Width ||
d3d101CaptureInfo.cy != scd.BufferDesc.Height )
if( dxgiFormat != scd.BufferDesc.Format ||
d3d101CaptureInfo.cx != scd.BufferDesc.Width ||
d3d101CaptureInfo.cy != scd.BufferDesc.Height ||
d3d101CaptureInfo.hwndCapture != (DWORD)scd.OutputWindow)
{
dxgiFormat = FixCopyTextureFormat(scd.BufferDesc.Format);
d3d101CaptureInfo.cx = scd.BufferDesc.Width;
d3d101CaptureInfo.cy = scd.BufferDesc.Height;
d3d101CaptureInfo.hwndCapture = (DWORD)scd.OutputWindow;
bIsMultisampled = scd.SampleDesc.Count > 1;
logOutput << "found dxgi format (dx10.1) of: " << UINT(dxgiFormat) <<
", size: {" << scd.BufferDesc.Width << ", " << scd.BufferDesc.Height <<
"}, multisampled: " << (bIsMultisampled ? "true" : "false") << endl;
}
}
}
@ -102,13 +110,13 @@ bool DoD3D101Hook(ID3D10Device *device)
ID3D10Texture2D *d3d101Tex;
if(FAILED(hErr = device->CreateTexture2D(&texGameDesc, NULL, &d3d101Tex)))
{
RUNONCE logOutput << "DoD3D101Hook: failed to create intermediary texture, result = " << UINT(hErr) << endl;
RUNEVERYRESET logOutput << "DoD3D101Hook: failed to create intermediary texture, result = " << UINT(hErr) << endl;
return false;
}
if(FAILED(hErr = d3d101Tex->QueryInterface(__uuidof(ID3D10Resource), (void**)&copyD3D101TextureGame)))
{
RUNONCE logOutput << "DoD3D101Hook: d3d101Tex->QueryInterface(ID3D10Resource) failed, result = " << UINT(hErr) << endl;
RUNEVERYRESET logOutput << "DoD3D101Hook: d3d101Tex->QueryInterface(ID3D10Resource) failed, result = " << UINT(hErr) << endl;
d3d101Tex->Release();
return false;
}
@ -116,14 +124,14 @@ bool DoD3D101Hook(ID3D10Device *device)
IDXGIResource *res;
if(FAILED(hErr = d3d101Tex->QueryInterface(IID_IDXGIResource, (void**)&res)))
{
RUNONCE logOutput << "DoD3D101Hook: d3d101Tex->QueryInterface(IDXGIResource) failed, result = " << UINT(hErr) << endl;
RUNEVERYRESET logOutput << "DoD3D101Hook: d3d101Tex->QueryInterface(IDXGIResource) failed, result = " << UINT(hErr) << endl;
d3d101Tex->Release();
return false;
}
if(FAILED(res->GetSharedHandle(&sharedHandle)))
{
RUNONCE logOutput << "DoD3D101Hook: res->GetSharedHandle failed, result = " << UINT(hErr) << endl;
RUNEVERYRESET logOutput << "DoD3D101Hook: res->GetSharedHandle failed, result = " << UINT(hErr) << endl;
d3d101Tex->Release();
res->Release();
return false;

View File

@ -52,6 +52,9 @@ void ClearD3D10Data()
DestroySharedMemory();
keepAliveTime = 0;
resetCount++;
logOutput << "---------------------- Cleared D3D10 Capture ----------------------" << endl;
}
void SetupD3D10(IDXGISwapChain *swapChain)
@ -64,15 +67,20 @@ void SetupD3D10(IDXGISwapChain *swapChain)
d3d10CaptureInfo.format = ConvertGIBackBufferFormat(scd.BufferDesc.Format);
if(d3d10CaptureInfo.format != GS_UNKNOWNFORMAT)
{
if( dxgiFormat != scd.BufferDesc.Format ||
d3d10CaptureInfo.cx != scd.BufferDesc.Width ||
d3d10CaptureInfo.cy != scd.BufferDesc.Height )
if( dxgiFormat != scd.BufferDesc.Format ||
d3d10CaptureInfo.cx != scd.BufferDesc.Width ||
d3d10CaptureInfo.cy != scd.BufferDesc.Height ||
d3d10CaptureInfo.hwndCapture != (DWORD)scd.OutputWindow)
{
dxgiFormat = FixCopyTextureFormat(scd.BufferDesc.Format);
d3d10CaptureInfo.cx = scd.BufferDesc.Width;
d3d10CaptureInfo.cy = scd.BufferDesc.Height;
d3d10CaptureInfo.hwndCapture = (DWORD)scd.OutputWindow;
bIsMultisampled = scd.SampleDesc.Count > 1;
logOutput << "found dxgi format (dx10) of: " << UINT(dxgiFormat) <<
", size: {" << scd.BufferDesc.Width << ", " << scd.BufferDesc.Height <<
"}, multisampled: " << (bIsMultisampled ? "true" : "false") << endl;
}
}
}
@ -103,13 +111,13 @@ bool DoD3D10Hook(ID3D10Device *device)
ID3D10Texture2D *d3d10Tex;
if(FAILED(hErr = device->CreateTexture2D(&texGameDesc, NULL, &d3d10Tex)))
{
RUNONCE logOutput << "DoD3D10Hook: failed to create intermediary texture, result = " << UINT(hErr) << endl;
RUNEVERYRESET logOutput << "DoD3D10Hook: failed to create intermediary texture, result = " << UINT(hErr) << endl;
return false;
}
if(FAILED(hErr = d3d10Tex->QueryInterface(__uuidof(ID3D10Resource), (void**)&copyD3D10TextureGame)))
{
RUNONCE logOutput << "DoD3D10Hook: d3d10Tex->QueryInterface(ID3D10Resource) failed, result = " << UINT(hErr) << endl;
RUNEVERYRESET logOutput << "DoD3D10Hook: d3d10Tex->QueryInterface(ID3D10Resource) failed, result = " << UINT(hErr) << endl;
d3d10Tex->Release();
return false;
}
@ -117,14 +125,14 @@ bool DoD3D10Hook(ID3D10Device *device)
IDXGIResource *res;
if(FAILED(hErr = d3d10Tex->QueryInterface(IID_IDXGIResource, (void**)&res)))
{
RUNONCE logOutput << "DoD3D10Hook: d3d10Tex->QueryInterface(IDXGIResource) failed, result = " << UINT(hErr) << endl;
RUNEVERYRESET logOutput << "DoD3D10Hook: d3d10Tex->QueryInterface(IDXGIResource) failed, result = " << UINT(hErr) << endl;
d3d10Tex->Release();
return false;
}
if(FAILED(res->GetSharedHandle(&sharedHandle)))
{
RUNONCE logOutput << "DoD3D10Hook: res->GetSharedHandle failed, result = " << UINT(hErr) << endl;
RUNEVERYRESET logOutput << "DoD3D10Hook: res->GetSharedHandle failed, result = " << UINT(hErr) << endl;
d3d10Tex->Release();
res->Release();
return false;

View File

@ -54,6 +54,9 @@ void ClearD3D11Data()
DestroySharedMemory();
keepAliveTime = 0;
resetCount++;
logOutput << "---------------------- Cleared D3D11 Capture ----------------------" << endl;
}
void SetupD3D11(IDXGISwapChain *swapChain)
@ -66,15 +69,20 @@ void SetupD3D11(IDXGISwapChain *swapChain)
d3d11CaptureInfo.format = ConvertGIBackBufferFormat(scd.BufferDesc.Format);
if(d3d11CaptureInfo.format != GS_UNKNOWNFORMAT)
{
if( dxgiFormat != scd.BufferDesc.Format ||
d3d11CaptureInfo.cx != scd.BufferDesc.Width ||
d3d11CaptureInfo.cy != scd.BufferDesc.Height )
if( dxgiFormat != scd.BufferDesc.Format ||
d3d11CaptureInfo.cx != scd.BufferDesc.Width ||
d3d11CaptureInfo.cy != scd.BufferDesc.Height ||
d3d11CaptureInfo.hwndCapture != (DWORD)scd.OutputWindow)
{
dxgiFormat = FixCopyTextureFormat(scd.BufferDesc.Format);
d3d11CaptureInfo.cx = scd.BufferDesc.Width;
d3d11CaptureInfo.cy = scd.BufferDesc.Height;
d3d11CaptureInfo.hwndCapture = (DWORD)scd.OutputWindow;
bIsMultisampled = scd.SampleDesc.Count > 1;
logOutput << "found dxgi format (dx11) of: " << UINT(dxgiFormat) <<
", size: {" << scd.BufferDesc.Width << ", " << scd.BufferDesc.Height <<
"}, multisampled: " << (bIsMultisampled ? "true" : "false") << endl;
}
}
}
@ -105,13 +113,13 @@ bool DoD3D11Hook(ID3D11Device *device)
ID3D11Texture2D *d3d11Tex;
if(FAILED(hErr = device->CreateTexture2D(&texGameDesc, NULL, &d3d11Tex)))
{
RUNONCE logOutput << "DoD3D11Hook: creation of intermediary texture failed, result = " << UINT(hErr) << endl;
RUNEVERYRESET logOutput << "DoD3D11Hook: creation of intermediary texture failed, result = " << UINT(hErr) << endl;
return false;
}
if(FAILED(hErr = d3d11Tex->QueryInterface(__uuidof(ID3D11Resource), (void**)&copyTextureGame)))
{
RUNONCE logOutput << "DoD3D11Hook: d3d11Tex->QueryInterface(ID3D11Resource) failed, result = " << UINT(hErr) << endl;
RUNEVERYRESET logOutput << "DoD3D11Hook: d3d11Tex->QueryInterface(ID3D11Resource) failed, result = " << UINT(hErr) << endl;
d3d11Tex->Release();
return false;
}
@ -119,14 +127,14 @@ bool DoD3D11Hook(ID3D11Device *device)
IDXGIResource *res;
if(FAILED(hErr = d3d11Tex->QueryInterface(IID_IDXGIResource, (void**)&res)))
{
RUNONCE logOutput << "DoD3D11Hook: d3d11Tex->QueryInterface(IID_IDXGIResource) failed, result = " << UINT(hErr) << endl;
RUNEVERYRESET logOutput << "DoD3D11Hook: d3d11Tex->QueryInterface(IID_IDXGIResource) failed, result = " << UINT(hErr) << endl;
d3d11Tex->Release();
return false;
}
if(FAILED(hErr = res->GetSharedHandle(&sharedHandle)))
{
RUNONCE logOutput << "DoD3D11Hook: res->GetSharedHandle failed, result = " << UINT(hErr) << endl;
RUNEVERYRESET logOutput << "DoD3D11Hook: res->GetSharedHandle failed, result = " << UINT(hErr) << endl;
d3d11Tex->Release();
res->Release();
return false;
@ -209,7 +217,7 @@ void DoD3D11Capture(IDXGISwapChain *swap)
d3d11CaptureInfo.mapID = InitializeSharedMemoryGPUCapture(&texData);
if(!d3d11CaptureInfo.mapID)
{
RUNONCE logOutput << "SwapPresentHook: creation of shared memory failed" << endl;
RUNEVERYRESET logOutput << "SwapPresentHook: creation of shared memory failed" << endl;
bSuccess = false;
}
}

View File

@ -203,7 +203,10 @@ void ClearD3D9Data()
curCapture = 0;
curCPUTexture = 0;
keepAliveTime = 0;
resetCount++;
pCopyData = NULL;
logOutput << "---------------------- Cleared D3D9 Capture ----------------------" << endl;
}
GSColorFormat ConvertDX9BackBufferFormat(D3DFORMAT format)
@ -248,42 +251,42 @@ void DoD3D9GPUHook(IDirect3DDevice9 *device)
HMODULE hD3D10_1 = LoadLibrary(TEXT("d3d10_1.dll"));
if(!hD3D10_1)
{
RUNONCE logOutput << "DoD3D9GPUHook: Could not load D3D10.1" << endl;
RUNEVERYRESET logOutput << "DoD3D9GPUHook: Could not load D3D10.1" << endl;
goto finishGPUHook;
}
HMODULE hDXGI = LoadLibrary(TEXT("dxgi.dll"));
if(!hDXGI)
{
RUNONCE logOutput << "DoD3D9GPUHook: Could not load dxgi" << endl;
RUNEVERYRESET logOutput << "DoD3D9GPUHook: Could not load dxgi" << endl;
goto finishGPUHook;
}
CREATEDXGIFACTORY1PROC createDXGIFactory1 = (CREATEDXGIFACTORY1PROC)GetProcAddress(hDXGI, "CreateDXGIFactory1");
if(!createDXGIFactory1)
{
RUNONCE logOutput << "DoD3D9GPUHook: Could not load 'CreateDXGIFactory1'" << endl;
RUNEVERYRESET logOutput << "DoD3D9GPUHook: Could not load 'CreateDXGIFactory1'" << endl;
goto finishGPUHook;
}
PFN_D3D10_CREATE_DEVICE1 d3d10CreateDevice1 = (PFN_D3D10_CREATE_DEVICE1)GetProcAddress(hD3D10_1, "D3D10CreateDevice1");
if(!d3d10CreateDevice1)
{
RUNONCE logOutput << "DoD3D9GPUHook: Could not load 'D3D10CreateDevice1'" << endl;
RUNEVERYRESET logOutput << "DoD3D9GPUHook: Could not load 'D3D10CreateDevice1'" << endl;
goto finishGPUHook;
}
IDXGIFactory1 *factory;
if(FAILED(hErr = (*createDXGIFactory1)(__uuidof(IDXGIFactory1), (void**)&factory)))
{
RUNONCE logOutput << "DoD3D9GPUHook: CreateDXGIFactory1 failed, result = " << (UINT)hErr << endl;
RUNEVERYRESET logOutput << "DoD3D9GPUHook: CreateDXGIFactory1 failed, result = " << (UINT)hErr << endl;
goto finishGPUHook;
}
IDXGIAdapter1 *adapter;
if(FAILED(hErr = factory->EnumAdapters1(0, &adapter)))
{
RUNONCE logOutput << "DoD3D9GPUHook: factory->EnumAdapters1 failed, result = " << (UINT)hErr << endl;
RUNEVERYRESET logOutput << "DoD3D9GPUHook: factory->EnumAdapters1 failed, result = " << (UINT)hErr << endl;
factory->Release();
goto finishGPUHook;
}
@ -292,7 +295,7 @@ void DoD3D9GPUHook(IDirect3DDevice9 *device)
{
if(FAILED(hErr = (*d3d10CreateDevice1)(adapter, D3D10_DRIVER_TYPE_HARDWARE, NULL, 0, D3D10_FEATURE_LEVEL_9_3, D3D10_1_SDK_VERSION, &shareDevice)))
{
RUNONCE logOutput << "DoD3D9GPUHook: Could not create D3D10.1 device, result = " << (UINT)hErr << endl;
RUNEVERYRESET logOutput << "DoD3D9GPUHook: Could not create D3D10.1 device, result = " << (UINT)hErr << endl;
adapter->Release();
factory->Release();
goto finishGPUHook;
@ -318,13 +321,13 @@ void DoD3D9GPUHook(IDirect3DDevice9 *device)
ID3D10Texture2D *d3d101Tex;
if(FAILED(hErr = shareDevice->CreateTexture2D(&texGameDesc, NULL, &d3d101Tex)))
{
RUNONCE logOutput << "DoD3D9GPUHook: shareDevice->CreateTexture2D failed, result = " << (UINT)hErr << endl;
RUNEVERYRESET logOutput << "DoD3D9GPUHook: shareDevice->CreateTexture2D failed, result = " << (UINT)hErr << endl;
goto finishGPUHook;
}
if(FAILED(hErr = d3d101Tex->QueryInterface(__uuidof(ID3D10Resource), (void**)&copyTextureIntermediary)))
{
RUNONCE logOutput << "DoD3D9GPUHook: d3d101Tex->QueryInterface(ID3D10Resource) failed, result = " << (UINT)hErr << endl;
RUNEVERYRESET logOutput << "DoD3D9GPUHook: d3d101Tex->QueryInterface(ID3D10Resource) failed, result = " << (UINT)hErr << endl;
d3d101Tex->Release();
goto finishGPUHook;
}
@ -332,14 +335,14 @@ void DoD3D9GPUHook(IDirect3DDevice9 *device)
IDXGIResource *res;
if(FAILED(hErr = d3d101Tex->QueryInterface(IID_IDXGIResource, (void**)&res)))
{
RUNONCE logOutput << "DoD3D9GPUHook: d3d101Tex->QueryInterface(IDXGIResource) failed, result = " << (UINT)hErr << endl;
RUNEVERYRESET logOutput << "DoD3D9GPUHook: d3d101Tex->QueryInterface(IDXGIResource) failed, result = " << (UINT)hErr << endl;
d3d101Tex->Release();
goto finishGPUHook;
}
if(FAILED(res->GetSharedHandle(&sharedHandle)))
{
RUNONCE logOutput << "DoD3D9GPUHook: res->GetSharedHandle failed, result = " << (UINT)hErr << endl;
RUNEVERYRESET logOutput << "DoD3D9GPUHook: res->GetSharedHandle failed, result = " << (UINT)hErr << endl;
d3d101Tex->Release();
res->Release();
goto finishGPUHook;
@ -364,7 +367,7 @@ void DoD3D9GPUHook(IDirect3DDevice9 *device)
}
else
{
RUNONCE logOutput << "DoD3D9GPUHook: unable to change memory protection, result = " << GetLastError() << endl;
RUNEVERYRESET logOutput << "DoD3D9GPUHook: unable to change memory protection, result = " << GetLastError() << endl;
goto finishGPUHook;
}
}
@ -372,7 +375,7 @@ void DoD3D9GPUHook(IDirect3DDevice9 *device)
IDirect3DTexture9 *d3d9Tex;
if(FAILED(hErr = device->CreateTexture(d3d9CaptureInfo.cx, d3d9CaptureInfo.cy, 1, D3DUSAGE_RENDERTARGET, (D3DFORMAT)d3d9Format, D3DPOOL_DEFAULT, &d3d9Tex, &sharedHandle)))
{
RUNONCE logOutput << "DoD3D9GPUHook: opening intermediary texture failed, result = " << (UINT)hErr << endl;
RUNEVERYRESET logOutput << "DoD3D9GPUHook: opening intermediary texture failed, result = " << (UINT)hErr << endl;
goto finishGPUHook;
}
@ -384,7 +387,7 @@ void DoD3D9GPUHook(IDirect3DDevice9 *device)
if(FAILED(hErr = d3d9Tex->GetSurfaceLevel(0, &copyD3D9TextureGame)))
{
RUNONCE logOutput << "DoD3D9GPUHook: d3d9Tex->GetSurfaceLevel failed, result = " << (UINT)hErr << endl;
RUNEVERYRESET logOutput << "DoD3D9GPUHook: d3d9Tex->GetSurfaceLevel failed, result = " << (UINT)hErr << endl;
d3d9Tex->Release();
goto finishGPUHook;
}
@ -394,7 +397,7 @@ void DoD3D9GPUHook(IDirect3DDevice9 *device)
d3d9CaptureInfo.mapID = InitializeSharedMemoryGPUCapture(&texData);
if(!d3d9CaptureInfo.mapID)
{
RUNONCE logOutput << "DoD3D9GPUHook: failed to initialize shared memory" << endl;
RUNEVERYRESET logOutput << "DoD3D9GPUHook: failed to initialize shared memory" << endl;
goto finishGPUHook;
}
@ -410,9 +413,15 @@ finishGPUHook:
texData->texHandle = (DWORD)sharedHandle;
memcpy(infoMem, &d3d9CaptureInfo, sizeof(CaptureInfo));
SetEvent(hSignalReady);
if (!SetEvent(hSignalReady))
logOutput << "SetEvent(hSignalReady) failed, GetLastError = " << UINT(GetLastError()) << endl;
logOutput << "DoD3D9GPUHook: success" << endl;
logOutput << "DoD3D9GPUHook: success";
if (bD3D9Ex)
logOutput << " - d3d9ex";
logOutput << endl;
}
else
ClearD3D9Data();
@ -430,7 +439,7 @@ void DoD3D9CPUHook(IDirect3DDevice9 *device)
{
if(FAILED(hErr = device->CreateOffscreenPlainSurface(d3d9CaptureInfo.cx, d3d9CaptureInfo.cy, (D3DFORMAT)d3d9Format, D3DPOOL_SYSTEMMEM, &textures[i], NULL)))
{
RUNONCE logOutput << "DoD3D9CPUHook: device->CreateOffscreenPlainSurface " << i << " failed, result = " << (UINT)hErr << endl;
RUNEVERYRESET logOutput << "DoD3D9CPUHook: device->CreateOffscreenPlainSurface " << i << " failed, result = " << (UINT)hErr << endl;
bSuccess = false;
break;
}
@ -440,7 +449,7 @@ void DoD3D9CPUHook(IDirect3DDevice9 *device)
D3DLOCKED_RECT lr;
if(FAILED(hErr = textures[i]->LockRect(&lr, NULL, D3DLOCK_READONLY)))
{
RUNONCE logOutput << "DoD3D9CPUHook: textures[" << i << "]->LockRect failed, result = " << (UINT)hErr << endl;
RUNEVERYRESET logOutput << "DoD3D9CPUHook: textures[" << i << "]->LockRect failed, result = " << (UINT)hErr << endl;
bSuccess = false;
break;
}
@ -456,21 +465,21 @@ void DoD3D9CPUHook(IDirect3DDevice9 *device)
{
if(FAILED(hErr = device->CreateRenderTarget(d3d9CaptureInfo.cx, d3d9CaptureInfo.cy, (D3DFORMAT)d3d9Format, D3DMULTISAMPLE_NONE, 0, FALSE, &copyD3D9Textures[i], NULL)))
{
RUNONCE logOutput << "DoD3D9CPUHook: device->CreateTexture " << i << " failed, result = " << (UINT)hErr << endl;
RUNEVERYRESET logOutput << "DoD3D9CPUHook: device->CreateTexture " << i << " failed, result = " << (UINT)hErr << endl;
bSuccess = false;
break;
}
if(FAILED(hErr = device->CreateQuery(D3DQUERYTYPE_EVENT, &queries[i])))
{
RUNONCE logOutput << "DoD3D9CPUHook: device->CreateQuery " << i << " failed, result = " << (UINT)hErr << endl;
RUNEVERYRESET logOutput << "DoD3D9CPUHook: device->CreateQuery " << i << " failed, result = " << (UINT)hErr << endl;
bSuccess = false;
break;
}
if(!(dataMutexes[i] = OSCreateMutex()))
{
RUNONCE logOutput << "DoD3D9CPUHook: OSCreateMutex " << i << " failed, GetLastError = " << GetLastError() << endl;
RUNEVERYRESET logOutput << "DoD3D9CPUHook: OSCreateMutex " << i << " failed, GetLastError = " << GetLastError() << endl;
bSuccess = false;
break;
}
@ -485,13 +494,13 @@ void DoD3D9CPUHook(IDirect3DDevice9 *device)
{
if(!(hCopyEvent = CreateEvent(NULL, FALSE, FALSE, NULL)))
{
RUNONCE logOutput << "DoD3D9CPUHook: CreateEvent failed, GetLastError = " << GetLastError() << endl;
RUNEVERYRESET logOutput << "DoD3D9CPUHook: CreateEvent failed, GetLastError = " << GetLastError() << endl;
bSuccess = false;
}
}
else
{
RUNONCE logOutput << "DoD3D9CPUHook: CreateThread failed, GetLastError = " << GetLastError() << endl;
RUNEVERYRESET logOutput << "DoD3D9CPUHook: CreateThread failed, GetLastError = " << GetLastError() << endl;
bSuccess = false;
}
}
@ -501,7 +510,7 @@ void DoD3D9CPUHook(IDirect3DDevice9 *device)
d3d9CaptureInfo.mapID = InitializeSharedMemoryCPUCapture(pitch*d3d9CaptureInfo.cy, &d3d9CaptureInfo.mapSize, &copyData, textureBuffers);
if(!d3d9CaptureInfo.mapID)
{
RUNONCE logOutput << "DoD3D9CPUHook: failed to initialize shared memory" << endl;
RUNEVERYRESET logOutput << "DoD3D9CPUHook: failed to initialize shared memory" << endl;
bSuccess = false;
}
}
@ -574,7 +583,7 @@ DWORD CopyD3D9CPUTextureThread(LPVOID lpUseless)
return 0;
}
void LogD3D9SurfaceInfo(IDirect3DSurface9 *surf);
void DoD3D9DrawStuff(IDirect3DDevice9 *device)
{
@ -590,8 +599,12 @@ void DoD3D9DrawStuff(IDirect3DDevice9 *device)
if(!bCapturing && WaitForSingleObject(hSignalRestart, 0) == WAIT_OBJECT_0)
{
hwndOBS = FindWindow(OBS_WINDOW_CLASS, NULL);
if(hwndOBS)
if(hwndOBS) {
logOutput << "received restart event, capturing" << endl;
bCapturing = true;
} else {
logOutput << "received restart event, but couldn't find window" << endl;
}
}
if(!bHasTextures && bCapturing)
@ -610,8 +623,6 @@ void DoD3D9DrawStuff(IDirect3DDevice9 *device)
}
}
//device->BeginScene();
LONGLONG timeVal = OSGetTimeMicroseconds();
//check keep alive state, dumb but effective
@ -670,14 +681,26 @@ void DoD3D9DrawStuff(IDirect3DDevice9 *device)
IDirect3DSurface9 *texture = textures[curCapture];
IDirect3DSurface9 *backBuffer = NULL;
if (SUCCEEDED(hErr = device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer))) {
if (FAILED(hErr = device->GetRenderTarget(0, &backBuffer))) {
RUNEVERYRESET logOutput << "D3D9DrawStuff: GetRenderTarget failed, result = " << unsigned int(hErr) << endl;
}
if (!backBuffer) {
if (FAILED(hErr = device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer))) {
RUNEVERYRESET logOutput << "DoD3D9DrawStuff: device->GetBackBuffer failed, result = " << unsigned int(hErr) << endl;
}
}
if (backBuffer) {
{RUNEVERYRESET LogD3D9SurfaceInfo(backBuffer);}
if (FAILED(hErr = device->StretchRect(backBuffer, NULL, copyD3D9TextureGame, NULL, D3DTEXF_NONE))) {
RUNONCE logOutput << "DoD3D9DrawStuff: device->StretchRect failed, result = " << unsigned int(hErr) << endl;
RUNEVERYRESET logOutput << "DoD3D9DrawStuff: device->StretchRect failed, result = " << unsigned int(hErr) << endl;
} else {
RUNEVERYRESET logOutput << "successfully capturing d3d9 frames via GPU" << endl;
}
backBuffer->Release();
} else {
RUNONCE logOutput << "DoD3D9DrawStuff: device->GetBackBuffer failed, result = " << unsigned int(hErr) << endl;
}
curCapture = nextCapture;
@ -762,6 +785,8 @@ void DoD3D9DrawStuff(IDirect3DDevice9 *device)
if(FAILED(hErr = device->GetRenderTargetData(prevSourceTexture, targetTexture)))
{
int test = 0;
} else {
RUNEVERYRESET logOutput << "successfully capturing d3d9 frames via CPU" << endl;
}
queries[nextCapture]->Issue(D3DISSUE_END);
@ -777,8 +802,6 @@ void DoD3D9DrawStuff(IDirect3DDevice9 *device)
else
ClearD3D9Data();
}
//device->EndScene();
}
@ -793,6 +816,8 @@ ULONG STDMETHODCALLTYPE D3D9Release(IDirect3DDevice9 *device)
{
if(refVal == 15)
{
logOutput << "d3d9 capture terminated by the application" << endl;
ClearD3D9Data();
lpCurrentDevice = NULL;
bTargetAcquired = false;
@ -802,8 +827,6 @@ ULONG STDMETHODCALLTYPE D3D9Release(IDirect3DDevice9 *device)
{
lpCurrentDevice = NULL;
bTargetAcquired = false;
logOutput << "d3d9 capture terminated by the application" << endl;
}
return (*(RELEASEPROC)oldD3D9Release)(device);
@ -813,6 +836,8 @@ HRESULT STDMETHODCALLTYPE D3D9EndScene(IDirect3DDevice9 *device)
{
d3d9EndScene.Unhook();
RUNEVERYRESET logOutput << "D3D9EndScene called" << endl;
if(lpCurrentDevice == NULL)
{
IDirect3D9 *d3d;
@ -842,6 +867,8 @@ HRESULT STDMETHODCALLTYPE D3D9Present(IDirect3DDevice9 *device, CONST RECT* pSou
{
d3d9Present.Unhook();
RUNEVERYRESET logOutput << "D3D9Present called" << endl;
if(!presentRecurse)
DoD3D9DrawStuff(device);
@ -859,6 +886,8 @@ HRESULT STDMETHODCALLTYPE D3D9PresentEx(IDirect3DDevice9Ex *device, CONST RECT*
{
d3d9PresentEx.Unhook();
RUNEVERYRESET logOutput << "D3D9PresentEx called" << endl;
if(!presentRecurse)
DoD3D9DrawStuff(device);
@ -876,6 +905,8 @@ HRESULT STDMETHODCALLTYPE D3D9SwapPresent(IDirect3DSwapChain9 *swap, CONST RECT*
{
d3d9SwapPresent.Unhook();
RUNEVERYRESET logOutput << "D3D9SwapPresent called" << endl;
if(!presentRecurse)
DoD3D9DrawStuff((IDirect3DDevice9*)lpCurrentDevice);
@ -893,6 +924,8 @@ HRESULT STDMETHODCALLTYPE D3D9Reset(IDirect3DDevice9 *device, D3DPRESENT_PARAMET
{
d3d9Reset.Unhook();
RUNEVERYRESET logOutput << "D3D9Reset called" << endl;
ClearD3D9Data();
HRESULT hRes = device->Reset(params);
@ -916,6 +949,8 @@ HRESULT STDMETHODCALLTYPE D3D9ResetEx(IDirect3DDevice9Ex *device, D3DPRESENT_PAR
d3d9ResetEx.Unhook();
d3d9Reset.Unhook();
RUNEVERYRESET logOutput << "D3D9ResetEx called" << endl;
ClearD3D9Data();
HRESULT hRes = device->ResetEx(params, fullscreenData);
@ -936,6 +971,7 @@ HRESULT STDMETHODCALLTYPE D3D9ResetEx(IDirect3DDevice9Ex *device, D3DPRESENT_PAR
return hRes;
}
void LogPresentParams(D3DPRESENT_PARAMETERS &pp);
void SetupD3D9(IDirect3DDevice9 *device)
{
@ -950,10 +986,13 @@ void SetupD3D9(IDirect3DDevice9 *device)
if(d3d9CaptureInfo.format != GS_UNKNOWNFORMAT)
{
if( d3d9Format != pp.BackBufferFormat ||
d3d9CaptureInfo.cx != pp.BackBufferWidth ||
d3d9CaptureInfo.cy != pp.BackBufferHeight )
if( d3d9Format != pp.BackBufferFormat ||
d3d9CaptureInfo.cx != pp.BackBufferWidth ||
d3d9CaptureInfo.cy != pp.BackBufferHeight ||
d3d9CaptureInfo.hwndCapture != (DWORD)pp.hDeviceWindow)
{
LogPresentParams(pp);
d3d9Format = pp.BackBufferFormat;
d3d9CaptureInfo.cx = pp.BackBufferWidth;
d3d9CaptureInfo.cy = pp.BackBufferHeight;
@ -971,30 +1010,36 @@ void SetupD3D9(IDirect3DDevice9 *device)
d3d->Release();
}
/*FARPROC curRelease = GetVTable(device, (8/4));
FARPROC curRelease = GetVTable(device, (8/4));
if(curRelease != newD3D9Release)
{
oldD3D9Release = curRelease;
newD3D9Release = (FARPROC)D3D9Release;
SetVTable(device, (8/4), newD3D9Release);
}*/
}
FARPROC curPresent = GetVTable(device, (68/4));
d3d9Present.Hook(curPresent, (FARPROC)D3D9Present);
d3d9Present.Hook(GetVTable(device, (68/4)), (FARPROC)D3D9Present);
if(bD3D9Ex)
{
FARPROC curPresentEx = GetVTable(device, (484/4));
d3d9PresentEx.Hook(curPresentEx, (FARPROC)D3D9PresentEx);
d3d9ResetEx.Hook(GetVTable(device, (528/4)), (FARPROC)D3D9ResetEx);
}
FARPROC curD3D9SwapPresent = GetVTable(swapChain, (12/4));
d3d9SwapPresent.Hook(curD3D9SwapPresent, (FARPROC)D3D9SwapPresent);
d3d9Reset.Hook(GetVTable(device, (64/4)), (FARPROC)D3D9Reset);
d3d9SwapPresent.Hook(GetVTable(swapChain, (12/4)), (FARPROC)D3D9SwapPresent);
d3d9Present.Rehook();
d3d9SwapPresent.Rehook();
d3d9Reset.Rehook();
if(bD3D9Ex)
if(bD3D9Ex) {
d3d9PresentEx.Rehook();
d3d9ResetEx.Rehook();
}
logOutput << "successfully set up d3d9 hooks" << endl;
swapChain->Release();
}
@ -1042,30 +1087,26 @@ bool InitD3D9Capture()
UPARAM *vtable = *(UPARAM**)deviceEx;
d3d9EndScene.Hook((FARPROC)*(vtable+(168/4)), (FARPROC)D3D9EndScene);
d3d9ResetEx.Hook((FARPROC)*(vtable+(528/4)), (FARPROC)D3D9ResetEx);
d3d9Reset.Hook((FARPROC)*(vtable+(64/4)), (FARPROC)D3D9Reset);
deviceEx->Release();
d3d9EndScene.Rehook();
d3d9Reset.Rehook();
d3d9ResetEx.Rehook();
}
else
{
RUNONCE logOutput << "InitD3D9Capture: d3d9ex->CreateDeviceEx failed, result: " << (UINT)hRes << endl;
RUNEVERYRESET logOutput << "InitD3D9Capture: d3d9ex->CreateDeviceEx failed, result: " << (UINT)hRes << endl;
}
d3d9ex->Release();
}
else
{
RUNONCE logOutput << "InitD3D9Capture: Direct3DCreate9Ex failed, result: " << (UINT)hRes << endl;
RUNEVERYRESET logOutput << "InitD3D9Capture: Direct3DCreate9Ex failed, result: " << (UINT)hRes << endl;
}
}
else
{
RUNONCE logOutput << "InitD3D9Capture: could not load address of Direct3DCreate9Ex" << endl;
RUNEVERYRESET logOutput << "InitD3D9Capture: could not load address of Direct3DCreate9Ex" << endl;
}
}

View File

@ -0,0 +1,377 @@
/********************************************************************************
Copyright (C) 2012 Hugh Bailey <obs.jim@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
********************************************************************************/
#include "GraphicsCaptureHook.h"
#include <d3d9.h>
static string GetD3D9FormatName(DWORD format)
{
switch(format) {
case D3DFMT_UNKNOWN : return string("D3DFMT_UNKNOWN");
case D3DFMT_R8G8B8 : return string("D3DFMT_R8G8B8");
case D3DFMT_A8R8G8B8 : return string("D3DFMT_A8R8G8B8");
case D3DFMT_X8R8G8B8 : return string("D3DFMT_X8R8G8B8");
case D3DFMT_R5G6B5 : return string("D3DFMT_R5G6B5");
case D3DFMT_X1R5G5B5 : return string("D3DFMT_X1R5G5B5");
case D3DFMT_A1R5G5B5 : return string("D3DFMT_A1R5G5B5");
case D3DFMT_A4R4G4B4 : return string("D3DFMT_A4R4G4B4");
case D3DFMT_R3G3B2 : return string("D3DFMT_R3G3B2");
case D3DFMT_A8 : return string("D3DFMT_A8");
case D3DFMT_A8R3G3B2 : return string("D3DFMT_A8R3G3B2");
case D3DFMT_X4R4G4B4 : return string("D3DFMT_X4R4G4B4");
case D3DFMT_A2B10G10R10 : return string("D3DFMT_A2B10G10R10");
case D3DFMT_A8B8G8R8 : return string("D3DFMT_A8B8G8R8");
case D3DFMT_X8B8G8R8 : return string("D3DFMT_X8B8G8R8");
case D3DFMT_G16R16 : return string("D3DFMT_G16R16");
case D3DFMT_A2R10G10B10 : return string("D3DFMT_A2R10G10B10");
case D3DFMT_A16B16G16R16 : return string("D3DFMT_A16B16G16R16");
case D3DFMT_A8P8 : return string("D3DFMT_A8P8");
case D3DFMT_P8 : return string("D3DFMT_P8");
case D3DFMT_L8 : return string("D3DFMT_L8");
case D3DFMT_A8L8 : return string("D3DFMT_A8L8");
case D3DFMT_A4L4 : return string("D3DFMT_A4L4");
case D3DFMT_V8U8 : return string("D3DFMT_V8U8");
case D3DFMT_L6V5U5 : return string("D3DFMT_L6V5U5");
case D3DFMT_X8L8V8U8 : return string("D3DFMT_X8L8V8U8");
case D3DFMT_Q8W8V8U8 : return string("D3DFMT_Q8W8V8U8");
case D3DFMT_V16U16 : return string("D3DFMT_V16U16");
case D3DFMT_A2W10V10U10 : return string("D3DFMT_A2W10V10U10");
case D3DFMT_UYVY : return string("D3DFMT_UYVY");
case D3DFMT_R8G8_B8G8 : return string("D3DFMT_R8G8_B8G8");
case D3DFMT_YUY2 : return string("D3DFMT_YUY2");
case D3DFMT_G8R8_G8B8 : return string("D3DFMT_G8R8_G8B8");
case D3DFMT_DXT1 : return string("D3DFMT_DXT1");
case D3DFMT_DXT2 : return string("D3DFMT_DXT2");
case D3DFMT_DXT3 : return string("D3DFMT_DXT3");
case D3DFMT_DXT4 : return string("D3DFMT_DXT4");
case D3DFMT_DXT5 : return string("D3DFMT_DXT5");
case D3DFMT_D16_LOCKABLE : return string("D3DFMT_D16_LOCKABLE");
case D3DFMT_D32 : return string("D3DFMT_D32");
case D3DFMT_D15S1 : return string("D3DFMT_D15S1");
case D3DFMT_D24S8 : return string("D3DFMT_D24S8");
case D3DFMT_D24X8 : return string("D3DFMT_D24X8");
case D3DFMT_D24X4S4 : return string("D3DFMT_D24X4S4");
case D3DFMT_D16 : return string("D3DFMT_D16");
case D3DFMT_D32F_LOCKABLE : return string("D3DFMT_D32F_LOCKABLE");
case D3DFMT_D24FS8 : return string("D3DFMT_D24FS8");
case D3DFMT_D32_LOCKABLE : return string("D3DFMT_D32_LOCKABLE");
case D3DFMT_S8_LOCKABLE : return string("D3DFMT_S8_LOCKABLE");
case D3DFMT_L16 : return string("D3DFMT_L16");
case D3DFMT_VERTEXDATA : return string("D3DFMT_VERTEXDATA");
case D3DFMT_INDEX16 : return string("D3DFMT_INDEX16");
case D3DFMT_INDEX32 : return string("D3DFMT_INDEX32");
case D3DFMT_Q16W16V16U16 : return string("D3DFMT_Q16W16V16U16");
case D3DFMT_MULTI2_ARGB8 : return string("D3DFMT_MULTI2_ARGB8");
case D3DFMT_R16F : return string("D3DFMT_R16F");
case D3DFMT_G16R16F : return string("D3DFMT_G16R16F");
case D3DFMT_A16B16G16R16F : return string("D3DFMT_A16B16G16R16F");
case D3DFMT_R32F : return string("D3DFMT_R32F");
case D3DFMT_G32R32F : return string("D3DFMT_G32R32F");
case D3DFMT_A32B32G32R32F : return string("D3DFMT_A32B32G32R32F");
case D3DFMT_CxV8U8 : return string("D3DFMT_CxV8U8");
case D3DFMT_A1 : return string("D3DFMT_A1");
case D3DFMT_A2B10G10R10_XR_BIAS : return string("D3DFMT_A2B10G10R10_XR_BIAS");
case D3DFMT_BINARYBUFFER : return string("D3DFMT_BINARYBUFFER");
}
return IntString(format);
}
static string GetD3D9MultiSampleTypeName(DWORD mst)
{
switch(mst) {
case D3DMULTISAMPLE_NONE : return string("D3DMULTISAMPLE_NONE");
case D3DMULTISAMPLE_NONMASKABLE : return string("D3DMULTISAMPLE_NONMASKABLE");
case D3DMULTISAMPLE_2_SAMPLES : return string("D3DMULTISAMPLE_2_SAMPLES");
case D3DMULTISAMPLE_3_SAMPLES : return string("D3DMULTISAMPLE_3_SAMPLES");
case D3DMULTISAMPLE_4_SAMPLES : return string("D3DMULTISAMPLE_4_SAMPLES");
case D3DMULTISAMPLE_5_SAMPLES : return string("D3DMULTISAMPLE_5_SAMPLES");
case D3DMULTISAMPLE_6_SAMPLES : return string("D3DMULTISAMPLE_6_SAMPLES");
case D3DMULTISAMPLE_7_SAMPLES : return string("D3DMULTISAMPLE_7_SAMPLES");
case D3DMULTISAMPLE_8_SAMPLES : return string("D3DMULTISAMPLE_8_SAMPLES");
case D3DMULTISAMPLE_9_SAMPLES : return string("D3DMULTISAMPLE_9_SAMPLES");
case D3DMULTISAMPLE_10_SAMPLES : return string("D3DMULTISAMPLE_10_SAMPLES");
case D3DMULTISAMPLE_11_SAMPLES : return string("D3DMULTISAMPLE_11_SAMPLES");
case D3DMULTISAMPLE_12_SAMPLES : return string("D3DMULTISAMPLE_12_SAMPLES");
case D3DMULTISAMPLE_13_SAMPLES : return string("D3DMULTISAMPLE_13_SAMPLES");
case D3DMULTISAMPLE_14_SAMPLES : return string("D3DMULTISAMPLE_14_SAMPLES");
case D3DMULTISAMPLE_15_SAMPLES : return string("D3DMULTISAMPLE_15_SAMPLES");
case D3DMULTISAMPLE_16_SAMPLES : return string("D3DMULTISAMPLE_16_SAMPLES");
}
return IntString(mst);
}
static string GetD3D9SwapEffectName(DWORD se)
{
switch(se) {
case D3DSWAPEFFECT_DISCARD: return string("D3DSWAPEFFECT_DISCARD");
case D3DSWAPEFFECT_FLIP : return string("D3DSWAPEFFECT_FLIP");
case D3DSWAPEFFECT_COPY : return string("D3DSWAPEFFECT_COPY");
case D3DSWAPEFFECT_OVERLAY: return string("D3DSWAPEFFECT_OVERLAY");
case D3DSWAPEFFECT_FLIPEX : return string("D3DSWAPEFFECT_FLIPEX");
}
return IntString(se);
}
static string GetD3D9D3DPPFlagsString(DWORD flags)
{
if (!flags)
return string("None");
stringstream ss;
if (flags & D3DPRESENTFLAG_LOCKABLE_BACKBUFFER) {
ss << "D3DPRESENTFLAG_LOCKABLE_BACKBUFFER ";
flags &= ~D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
}
if (flags & D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL) {
ss << "D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL ";
flags &= ~D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
}
if (flags & D3DPRESENTFLAG_DEVICECLIP) {
ss << "D3DPRESENTFLAG_DEVICECLIP ";
flags &= ~D3DPRESENTFLAG_DEVICECLIP;
}
if (flags & D3DPRESENTFLAG_VIDEO) {
ss << "D3DPRESENTFLAG_VIDEO ";
flags &= ~D3DPRESENTFLAG_VIDEO;
}
if (flags & D3DPRESENTFLAG_NOAUTOROTATE) {
ss << "D3DPRESENTFLAG_NOAUTOROTATE ";
flags &= ~D3DPRESENTFLAG_NOAUTOROTATE;
}
if (flags & D3DPRESENTFLAG_UNPRUNEDMODE) {
ss << "D3DPRESENTFLAG_UNPRUNEDMODE ";
flags &= ~D3DPRESENTFLAG_UNPRUNEDMODE;
}
if (flags & D3DPRESENTFLAG_OVERLAY_LIMITEDRGB) {
ss << "D3DPRESENTFLAG_OVERLAY_LIMITEDRGB ";
flags &= ~D3DPRESENTFLAG_OVERLAY_LIMITEDRGB;
}
if (flags & D3DPRESENTFLAG_OVERLAY_YCbCr_BT709) {
ss << "D3DPRESENTFLAG_OVERLAY_YCbCr_BT709 ";
flags &= ~D3DPRESENTFLAG_OVERLAY_YCbCr_BT709;
}
if (flags & D3DPRESENTFLAG_OVERLAY_YCbCr_xvYCC) {
ss << "D3DPRESENTFLAG_OVERLAY_YCbCr_xvYCC ";
flags &= ~D3DPRESENTFLAG_OVERLAY_YCbCr_xvYCC;
}
if (flags & D3DPRESENTFLAG_RESTRICTED_CONTENT) {
ss << "D3DPRESENTFLAG_RESTRICTED_CONTENT ";
flags &= ~D3DPRESENTFLAG_RESTRICTED_CONTENT;
}
if (flags & D3DPRESENTFLAG_RESTRICT_SHARED_RESOURCE_DRIVER) {
ss << "D3DPRESENTFLAG_RESTRICT_SHARED_RESOURCE_DRIVER ";
flags &= ~D3DPRESENTFLAG_RESTRICT_SHARED_RESOURCE_DRIVER;
}
if (flags)
ss << IntString(flags) << " ";
return ss.str();
}
static string GetD3D9ResourceTypeName(DWORD rt)
{
switch(rt) {
case D3DRTYPE_SURFACE : return string("D3DRTYPE_SURFACE");
case D3DRTYPE_VOLUME : return string("D3DRTYPE_VOLUME");
case D3DRTYPE_TEXTURE : return string("D3DRTYPE_TEXTURE");
case D3DRTYPE_VOLUMETEXTURE: return string("D3DRTYPE_VOLUMETEXTURE");
case D3DRTYPE_CUBETEXTURE : return string("D3DRTYPE_CUBETEXTURE");
case D3DRTYPE_VERTEXBUFFER : return string("D3DRTYPE_VERTEXBUFFER");
case D3DRTYPE_INDEXBUFFER : return string("D3DRTYPE_INDEXBUFFER");
}
return IntString(rt);
}
static string GetD3D9PoolName(DWORD pool)
{
switch(pool) {
case D3DPOOL_DEFAULT : return string("D3DPOOL_DEFAULT");
case D3DPOOL_MANAGED : return string("D3DPOOL_MANAGED");
case D3DPOOL_SYSTEMMEM: return string("D3DPOOL_SYSTEMMEM");
case D3DPOOL_SCRATCH : return string("D3DPOOL_SCRATCH");
}
return IntString(pool);
}
static string GetD3D9UsageString(DWORD flags)
{
if (!flags)
return string("None");
stringstream ss;
if (flags & D3DUSAGE_RENDERTARGET) {
ss << "D3DUSAGE_RENDERTARGET ";
flags &= ~D3DUSAGE_RENDERTARGET;
}
if (flags & D3DUSAGE_DEPTHSTENCIL) {
ss << "D3DUSAGE_DEPTHSTENCIL ";
flags &= ~D3DUSAGE_DEPTHSTENCIL;
}
if (flags & D3DUSAGE_DYNAMIC) {
ss << "D3DUSAGE_DYNAMIC ";
flags &= ~D3DUSAGE_DYNAMIC;
}
if (flags & D3DUSAGE_NONSECURE) {
ss << "D3DUSAGE_NONSECURE ";
flags &= ~D3DUSAGE_NONSECURE;
}
if (flags & D3DUSAGE_AUTOGENMIPMAP) {
ss << "D3DUSAGE_AUTOGENMIPMAP ";
flags &= ~D3DUSAGE_AUTOGENMIPMAP;
}
if (flags & D3DUSAGE_DMAP) {
ss << "D3DUSAGE_DMAP ";
flags &= ~D3DUSAGE_DMAP;
}
if (flags & D3DUSAGE_QUERY_LEGACYBUMPMAP) {
ss << "D3DUSAGE_QUERY_LEGACYBUMPMAP ";
flags &= ~D3DUSAGE_QUERY_LEGACYBUMPMAP;
}
if (flags & D3DUSAGE_QUERY_SRGBREAD) {
ss << "D3DUSAGE_QUERY_SRGBREAD ";
flags &= ~D3DUSAGE_QUERY_SRGBREAD;
}
if (flags & D3DUSAGE_QUERY_FILTER) {
ss << "D3DUSAGE_QUERY_FILTER ";
flags &= ~D3DUSAGE_QUERY_FILTER;
}
if (flags & D3DUSAGE_QUERY_SRGBWRITE) {
ss << "D3DUSAGE_QUERY_SRGBWRITE ";
flags &= ~D3DUSAGE_QUERY_SRGBWRITE;
}
if (flags & D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
ss << "D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING ";
flags &= ~D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
}
if (flags & D3DUSAGE_QUERY_VERTEXTEXTURE) {
ss << "D3DUSAGE_QUERY_VERTEXTEXTURE ";
flags &= ~D3DUSAGE_QUERY_VERTEXTEXTURE;
}
if (flags & D3DUSAGE_QUERY_WRAPANDMIP) {
ss << "D3DUSAGE_QUERY_WRAPANDMIP ";
flags &= ~D3DUSAGE_QUERY_WRAPANDMIP;
}
if (flags & D3DUSAGE_DYNAMIC) {
ss << "D3DUSAGE_DYNAMIC ";
flags &= ~D3DUSAGE_DYNAMIC;
}
if (flags & D3DUSAGE_WRITEONLY) {
ss << "D3DUSAGE_WRITEONLY ";
flags &= ~D3DUSAGE_WRITEONLY;
}
if (flags & D3DUSAGE_SOFTWAREPROCESSING) {
ss << "D3DUSAGE_SOFTWAREPROCESSING ";
flags &= ~D3DUSAGE_SOFTWAREPROCESSING;
}
if (flags & D3DUSAGE_DONOTCLIP) {
ss << "D3DUSAGE_DONOTCLIP ";
flags &= ~D3DUSAGE_DONOTCLIP;
}
if (flags & D3DUSAGE_POINTS) {
ss << "D3DUSAGE_POINTS ";
flags &= ~D3DUSAGE_POINTS;
}
if (flags & D3DUSAGE_RTPATCHES) {
ss << "D3DUSAGE_RTPATCHES ";
flags &= ~D3DUSAGE_RTPATCHES;
}
if (flags & D3DUSAGE_NPATCHES) {
ss << "D3DUSAGE_NPATCHES ";
flags &= ~D3DUSAGE_NPATCHES;
}
if (flags & D3DUSAGE_TEXTAPI) {
ss << "D3DUSAGE_TEXTAPI ";
flags &= ~D3DUSAGE_TEXTAPI;
}
if (flags & D3DUSAGE_RESTRICTED_CONTENT) {
ss << "D3DUSAGE_RESTRICTED_CONTENT ";
flags &= ~D3DUSAGE_RESTRICTED_CONTENT;
}
if (flags & D3DUSAGE_RESTRICT_SHARED_RESOURCE) {
ss << "D3DUSAGE_RESTRICT_SHARED_RESOURCE ";
flags &= ~D3DUSAGE_RESTRICT_SHARED_RESOURCE;
}
if (flags & D3DUSAGE_RESTRICT_SHARED_RESOURCE_DRIVER) {
ss << "D3DUSAGE_RESTRICT_SHARED_RESOURCE_DRIVER ";
flags &= ~D3DUSAGE_RESTRICT_SHARED_RESOURCE_DRIVER;
}
if (flags)
ss << IntString(flags) << " ";
return ss.str();
}
void LogPresentParams(D3DPRESENT_PARAMETERS &pp)
{
if (pp.hDeviceWindow) {
UINT testLen = GetWindowTextLength(pp.hDeviceWindow);
testLen++;
string strName;
strName.resize(testLen);
GetWindowTextA(pp.hDeviceWindow, (char*)strName.c_str(), testLen);
logOutput << "found d3d9 present params for window: " << strName << endl;
}
logOutput << "D3DPRESENT_PARAMETERS {" << endl;
logOutput << "\t" "BackBufferWidth: " << pp.BackBufferWidth << endl;
logOutput << "\t" "BackBufferHeight: " << pp.BackBufferHeight << endl;
logOutput << "\t" "BackBufferFormat: " << GetD3D9FormatName(pp.BackBufferFormat) << endl;
logOutput << "\t" "BackBufferCount: " << pp.BackBufferCount << endl;
logOutput << "\t" "MultiSampleType: " << GetD3D9MultiSampleTypeName(pp.MultiSampleType) << endl;
logOutput << "\t" "MultiSampleQuality: " << pp.MultiSampleQuality << endl;
logOutput << "\t" "SwapEffect: " << GetD3D9SwapEffectName(pp.SwapEffect) << endl;
logOutput << "\t" "hDeviceWindow: " << DWORD(pp.hDeviceWindow) << endl;
logOutput << "\t" "Windowed: " << (pp.Windowed ? "true" : "false") << endl;
logOutput << "\t" "EnableAutoDepthStencil: " << (pp.EnableAutoDepthStencil ? "true" : "false") << endl;
logOutput << "\t" "AutoDepthStencilFormat: " << GetD3D9FormatName(pp.AutoDepthStencilFormat) << endl;
logOutput << "\t" "Flags: " << GetD3D9D3DPPFlagsString(pp.Flags) << endl;
logOutput << "\t" "FullScreen_RefreshRateInHz: " << pp.FullScreen_RefreshRateInHz << endl;
logOutput << "\t" "PresentationInterval: " << pp.PresentationInterval << endl;
logOutput << "};" << endl;
}
void LogD3D9SurfaceInfo(IDirect3DSurface9 *surf)
{
if (!surf) return;
D3DSURFACE_DESC sd;
ZeroMemory(&sd, sizeof(sd));
if (SUCCEEDED(surf->GetDesc(&sd))) {
logOutput << "D3DSURFACE_DESC {" << endl;
logOutput << "\t" "Format: " << GetD3D9FormatName(sd.Format) << endl;
logOutput << "\t" "Type: " << GetD3D9ResourceTypeName(sd.Type) << endl;
logOutput << "\t" "Usage: " << GetD3D9UsageString(sd.Usage) << endl;
logOutput << "\t" "Pool: " << GetD3D9PoolName(sd.Pool) << endl;
logOutput << "\t" "MultiSampleType: " << GetD3D9MultiSampleTypeName(sd.MultiSampleType) << endl;
logOutput << "\t" "MultiSampleQuality: " << sd.MultiSampleQuality << endl;
logOutput << "\t" "Width: " << sd.Width << endl;
logOutput << "\t" "Height: " << sd.Height << endl;
logOutput << "};" << endl;
} else {
logOutput << "could not get D3DSURFACE_DESC from backbuffer for some reason" << endl;
}
}

View File

@ -172,11 +172,11 @@ IDXGISwapChain* CreateDummySwap()
return swap;
}
RUNONCE logOutput << "CreateDummySwap: D3D10CreateDeviceAndSwapChain failed, result = " << UINT(hErr) << endl;
RUNEVERYRESET logOutput << "CreateDummySwap: D3D10CreateDeviceAndSwapChain failed, result = " << UINT(hErr) << endl;
}
else
{
RUNONCE logOutput << "CreateDummySwap: D3D10CreateDeviceAndSwapChain not found" << endl;
RUNEVERYRESET logOutput << "CreateDummySwap: D3D10CreateDeviceAndSwapChain not found" << endl;
}
}
@ -200,11 +200,11 @@ IDXGISwapChain* CreateDummySwap()
return swap;
}
RUNONCE logOutput << "CreateDummyDevice: D3D10CreateDeviceAndSwapChain1 failed, result = " << UINT(hErr) << endl;
RUNEVERYRESET logOutput << "CreateDummyDevice: D3D10CreateDeviceAndSwapChain1 failed, result = " << UINT(hErr) << endl;
}
else
{
RUNONCE logOutput << "CreateDummyDevice: D3D10CreateDeviceAndSwapChain1 not found" << endl;
RUNEVERYRESET logOutput << "CreateDummyDevice: D3D10CreateDeviceAndSwapChain1 not found" << endl;
}
}
@ -240,11 +240,11 @@ IDXGISwapChain* CreateDummySwap()
return swap;
}
RUNONCE logOutput << "CreateDummyDevice: D3D11CreateDeviceAndSwapChain failed, result = " << UINT(hErr) << endl;
RUNEVERYRESET logOutput << "CreateDummyDevice: D3D11CreateDeviceAndSwapChain failed, result = " << UINT(hErr) << endl;
}
else
{
RUNONCE logOutput << "CreateDummyDevice: D3D11CreateDeviceAndSwapChain not found" << endl;
RUNEVERYRESET logOutput << "CreateDummyDevice: D3D11CreateDeviceAndSwapChain not found" << endl;
}
}

View File

@ -26,6 +26,7 @@ HANDLE hSignalReady=NULL, hSignalExit=NULL;
HINSTANCE hinstMain = NULL;
HWND hwndSender = NULL, hwndOBS = NULL;
HANDLE textureMutexes[2] = {NULL, NULL};
int resetCount = 1;
bool bStopRequested = false;
bool bCapturing = true;
bool bTargetAcquired = false;
@ -265,12 +266,14 @@ DWORD WINAPI CaptureThread(HANDLE hDllMainThread)
wcscat_s(lpLogPath, MAX_PATH, TEXT("\\OBS\\pluginData\\captureHookLog.txt"));
if(!logOutput.is_open())
logOutput.open(lpLogPath, ios_base::in | ios_base::out | ios_base::trunc);
logOutput.open(lpLogPath, ios_base::in | ios_base::out | ios_base::trunc, _SH_DENYNO);
wstringstream str;
str << OBS_KEEPALIVE_EVENT << int(GetCurrentProcessId());
str << OBS_KEEPALIVE_EVENT << UINT(GetCurrentProcessId());
strKeepAlive = str.str();
logOutput << "we're booting up.." << endl;
WNDCLASS wc;
ZeroMemory(&wc, sizeof(wc));
wc.hInstance = hinstMain;
@ -314,41 +317,47 @@ DWORD WINAPI CaptureThread(HANDLE hDllMainThread)
return 0;
}
if(RegisterClass(&wc))
{
if (RegisterClass(&wc)) {
hwndSender = CreateWindow(SENDER_WINDOWCLASS, NULL, 0, 0, 0, 0, 0, NULL, 0, hinstMain, 0);
if(hwndSender)
{
if (hwndSender) {
textureMutexes[0] = OpenMutex(MUTEX_ALL_ACCESS, FALSE, TEXTURE_MUTEX1);
if(textureMutexes[0])
{
if (textureMutexes[0]) {
textureMutexes[1] = OpenMutex(MUTEX_ALL_ACCESS, FALSE, TEXTURE_MUTEX2);
if(textureMutexes[1])
{
while(!AttemptToHookSomething())
Sleep(50);
if (textureMutexes[1]) {
logOutput << "(half life scientist) everything.. seems to be in order" << endl;
MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
while (1) {
AttemptToHookSomething();
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Sleep(50);
}
CloseHandle(textureMutexes[1]);
textureMutexes[1] = NULL;
} else {
logOutput << "could not open texture mutex 2" << endl;
}
CloseHandle(textureMutexes[0]);
textureMutexes[0] = NULL;
} else {
logOutput << "could not open texture mutex 1" << endl;
}
DestroyWindow(hwndSender);
} else {
logOutput << "could not create sender window" << endl;
}
}
logOutput << "exit out of the main thread loop somehow" << endl;
return 0;
}

View File

@ -40,7 +40,9 @@ using namespace std;
//arghh I hate defines like this
#define RUNONCE static bool bRunOnce = false; if(!bRunOnce && (bRunOnce = true))
#define RUNONCE static bool bRunOnce = false; if(!bRunOnce && (bRunOnce = true))
#define RUNEVERY(v) static int __runCount = 0; if(__runCount == 50) __runCount = 0; if(!__runCount++)
#define RUNEVERYRESET static int __resetCount = 0; if(__resetCount != resetCount && (__resetCount = resetCount))
#define SafeRelease(var) if(var) {var->Release(); var = NULL;}
@ -195,6 +197,14 @@ inline void SSECopy(void *lpDest, void *lpSource, UINT size)
}
}
inline string IntString(DWORD val)
{
stringstream ss;
ss << val;
return ss.str();
}
typedef ULONG (WINAPI *RELEASEPROC)(LPVOID);
#include "../GlobalCaptureStuff.h"
@ -204,6 +214,7 @@ enum GSColorFormat {GS_UNKNOWNFORMAT, GS_ALPHA, GS_GRAYSCALE, GS_RGB, GS_RGBA, G
extern HINSTANCE hinstMain;
extern HANDLE textureMutexes[2];
extern bool bCapturing;
extern int resetCount;
extern bool bStopRequested;
extern bool bTargetAcquired;

View File

@ -219,6 +219,7 @@
<ClCompile Include="D3D10Capture.cpp" />
<ClCompile Include="D3D11Capture.cpp" />
<ClCompile Include="D3D9Capture.cpp" />
<ClCompile Include="D3D9LogStuff.cpp" />
<ClCompile Include="DDrawCapture.cpp" />
<ClCompile Include="DXGICapture.cpp" />
<ClCompile Include="GraphicsCaptureHook.cpp" />

View File

@ -39,6 +39,9 @@
<ClCompile Include="OpenGLCapture.cpp">
<Filter>Source</Filter>
</ClCompile>
<ClCompile Include="D3D9LogStuff.cpp">
<Filter>Source</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="DXGIStuff.h">

View File

@ -217,7 +217,10 @@ void ClearGLData()
curCapture = 0;
curCPUTexture = 0;
keepAliveTime = 0;
resetCount++;
pCopyData = NULL;
logOutput << "---------------------- Cleared OpenGL Capture ----------------------" << endl;
}
DWORD CopyGLCPUTextureThread(LPVOID lpUseless);

View File

@ -138,7 +138,7 @@ GraphicsCaptureSource::~GraphicsCaptureSource()
static bool GetCaptureInfo(CaptureInfo &ci, DWORD processID)
{
HANDLE hFileMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, String() << INFO_MEMORY << int(processID));
HANDLE hFileMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, String() << INFO_MEMORY << UINT(processID));
if(hFileMap == NULL)
{
AppWarning(TEXT("GetCaptureInfo: Could not open file mapping"));
@ -168,6 +168,7 @@ void GraphicsCaptureSource::NewCapture()
{
if(capture)
{
Log(TEXT("GraphicsCaptureSource::NewCapture: eliminating old capture"));
capture->Destroy();
delete capture;
capture = NULL;
@ -175,7 +176,7 @@ void GraphicsCaptureSource::NewCapture()
if(!hSignalRestart)
{
hSignalRestart = GetEvent(String() << RESTART_CAPTURE_EVENT << int(targetProcessID));
hSignalRestart = GetEvent(String() << RESTART_CAPTURE_EVENT << UINT(targetProcessID));
if(!hSignalRestart)
{
RUNONCE AppWarning(TEXT("GraphicsCaptureSource::NewCapture: Could not create restart event"));
@ -183,21 +184,21 @@ void GraphicsCaptureSource::NewCapture()
}
}
hSignalEnd = GetEvent(String() << END_CAPTURE_EVENT << int(targetProcessID));
hSignalEnd = GetEvent(String() << END_CAPTURE_EVENT << UINT(targetProcessID));
if(!hSignalEnd)
{
RUNONCE AppWarning(TEXT("GraphicsCaptureSource::NewCapture: Could not create end event"));
return;
}
hSignalReady = GetEvent(String() << CAPTURE_READY_EVENT << int(targetProcessID));
hSignalReady = GetEvent(String() << CAPTURE_READY_EVENT << UINT(targetProcessID));
if(!hSignalReady)
{
RUNONCE AppWarning(TEXT("GraphicsCaptureSource::NewCapture: Could not create ready event"));
return;
}
hSignalExit = GetEvent(String() << APP_EXIT_EVENT << int(targetProcessID));
hSignalExit = GetEvent(String() << APP_EXIT_EVENT << UINT(targetProcessID));
if(!hSignalExit)
{
RUNONCE AppWarning(TEXT("GraphicsCaptureSource::NewCapture: Could not create exit event"));
@ -352,13 +353,13 @@ void GraphicsCaptureSource::AttemptCapture()
//-------------------------------------------
// load keepalive event
hOBSIsAlive = CreateEvent(NULL, FALSE, FALSE, String() << OBS_KEEPALIVE_EVENT << int(targetProcessID));
hOBSIsAlive = CreateEvent(NULL, FALSE, FALSE, String() << OBS_KEEPALIVE_EVENT << UINT(targetProcessID));
//-------------------------------------------
hwndCapture = hwndTarget;
hSignalRestart = OpenEvent(EVENT_ALL_ACCESS, FALSE, String() << RESTART_CAPTURE_EVENT << int(targetProcessID));
hSignalRestart = OpenEvent(EVENT_ALL_ACCESS, FALSE, String() << RESTART_CAPTURE_EVENT << UINT(targetProcessID));
if(hSignalRestart)
{
SetEvent(hSignalRestart);
@ -517,14 +518,36 @@ void GraphicsCaptureSource::EndScene()
void GraphicsCaptureSource::Tick(float fSeconds)
{
if(hSignalExit && WaitForSingleObject(hSignalExit, 0) == WAIT_OBJECT_0)
if(hSignalExit && WaitForSingleObject(hSignalExit, 0) == WAIT_OBJECT_0) {
Log(TEXT("Exit signal received, terminating capture"));
EndCapture();
}
if(bCapturing && !hSignalReady && targetProcessID)
hSignalReady = GetEvent(String() << CAPTURE_READY_EVENT << int(targetProcessID));
hSignalReady = GetEvent(String() << CAPTURE_READY_EVENT << UINT(targetProcessID));
if(hSignalReady && (WaitForSingleObject(hSignalReady, 0) == WAIT_OBJECT_0))
NewCapture();
if (hSignalReady) {
DWORD val = WaitForSingleObject(hSignalReady, 0);
if (val == WAIT_OBJECT_0)
NewCapture();
/*else if (val != WAIT_TIMEOUT)
Log(TEXT("what the heck? val is 0x%08lX"), val);*/
}
/* static int floong = 0;
if (floong++ == 30) {
Log(TEXT("valid, bCapturing = %s"), bCapturing ? TEXT("true") : TEXT("false"));
floong = 0;
}
} else {
static int floong = 0;
if (floong++ == 30) {
Log(TEXT("not valid, bCapturing = %s"), bCapturing ? TEXT("true") : TEXT("false"));
floong = 0;
}
}*/
if(bCapturing && !capture)
{
@ -546,10 +569,15 @@ void GraphicsCaptureSource::Tick(float fSeconds)
}
else
{
if(!IsWindow(hwndCapture) || (bUseHotkey && hwndNextTarget && hwndNextTarget != hwndTarget))
if(!IsWindow(hwndCapture)) {
Log(TEXT("Capture window 0x%08lX invalid or changing, terminating capture"), DWORD(hwndCapture));
EndCapture();
else
} else if (bUseHotkey && hwndNextTarget && hwndNextTarget != hwndTarget) {
Log(TEXT("Capture hotkey triggered for new window, terminating capture"));
EndCapture();
} else {
hwndNextTarget = NULL;
}
}
}
@ -748,7 +776,7 @@ void GraphicsCaptureSource::SetInt(CTSTR lpName, int iVal)
}
}
void GraphicsCaptureSource::CaptureHotkey(DWORD hotkey, GraphicsCaptureSource *capture, bool bDown)
void STDCALL GraphicsCaptureSource::CaptureHotkey(DWORD hotkey, GraphicsCaptureSource *capture, bool bDown)
{
if (bDown)
capture->hwndNextTarget = GetForegroundWindow();

View File

@ -58,7 +58,7 @@ class GraphicsCaptureSource : public ImageSource
void AttemptCapture();
static void CaptureHotkey(DWORD hotkey, GraphicsCaptureSource *capture, bool bDown);
static void STDCALL CaptureHotkey(DWORD hotkey, GraphicsCaptureSource *capture, bool bDown);
public:
bool Init(XElement *data);

View File

@ -0,0 +1,66 @@
/********************************************************************************
Copyright (C) 2012 Hugh Bailey <obs.jim@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
********************************************************************************/
#include "GraphicsCapture.h"
void WindowCapture::Destroy()
{
delete sharedTexture;
sharedTexture = NULL;
}
bool WindowCapture::Init(CaptureInfo &info)
{
hwndTarget = (HWND)info.hwndCapture;
cx = info.cx;
cy = info.cy;
if (!cx || !cy)
return false;
sharedTexture = CreateGDITexture(info.cx, info.cy);
return true;
}
Texture* WindowCapture::LockTexture()
{
HDC hdcTarget = GetDC(hwndTarget);
if (!hdcTarget) return NULL;
bool bSuccess = false;
HDC hDC;
if (sharedTexture->GetDC(hDC)) {
BitBlt(hDC, 0, 0, cx, cy, hdcTarget, 0, 0, SRCCOPY);
sharedTexture->ReleaseDC();
bSuccess = true;
}
ReleaseDC(hwndTarget, hdcTarget);
return bSuccess ? sharedTexture : NULL;
}
void WindowCapture::UnlockTexture()
{
}

View File

@ -0,0 +1,36 @@
/********************************************************************************
Copyright (C) 2012 Hugh Bailey <obs.jim@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
********************************************************************************/
#pragma once
class WindowCapture : public GraphicsCaptureMethod
{
Texture *sharedTexture;
HWND hwndTarget;
UINT cx, cy;
public:
void Destroy();
virtual bool Init(CaptureInfo &info);
virtual Texture* LockTexture();
virtual void UnlockTexture();
};