bool InitD3D11Capture() { bool bSuccess = false; HMODULE hD3D11Dll = GetModuleHandle(TEXT("d3d11.dll")); if(hD3D11Dll) { D3D11CREATEPROC d3d11Create = (D3D11CREATEPROC)GetProcAddress(hD3D11Dll, "D3D11CreateDeviceAndSwapChain"); if(d3d11Create) { DXGI_SWAP_CHAIN_DESC swapDesc; ZeroMemory(&swapDesc, sizeof(swapDesc)); swapDesc.BufferCount = 2; swapDesc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; swapDesc.BufferDesc.Width = 2; swapDesc.BufferDesc.Height = 2; swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapDesc.OutputWindow = hwndSender; swapDesc.SampleDesc.Count = 1; swapDesc.Windowed = TRUE; IDXGISwapChain *swap; ID3D11Device *device; ID3D11DeviceContext *context; D3D_FEATURE_LEVEL desiredLevel = D3D_FEATURE_LEVEL_11_0; D3D_FEATURE_LEVEL receivedLevel; HRESULT hErr; if(SUCCEEDED(hErr = (*d3d11Create)(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, &desiredLevel, 1, D3D11_SDK_VERSION, &swapDesc, &swap, &device, &receivedLevel, &context))) { bSuccess = true; UPARAM *vtable = *(UPARAM**)swap; gi11swapPresent.Hook((FARPROC)*(vtable+(32/4)), ConvertClassProcToFarproc((CLASSPROC)&D3D11Override::SwapPresentHook)); gi11swapResizeBuffers.Hook((FARPROC)*(vtable+(52/4)), ConvertClassProcToFarproc((CLASSPROC)&D3D11Override::SwapResizeBuffersHook)); SafeRelease(swap); SafeRelease(device); SafeRelease(context); gi11swapPresent.Rehook(); gi11swapResizeBuffers.Rehook(); } } } return bSuccess; }
bool InitGLCapture() { bool bSuccess = false; HMODULE hGL = GetModuleHandle(TEXT("opengl32.dll")); if(hGL) { pglReadBuffer = (GLREADBUFFERPROC) GetProcAddress(hGL, "glReadBuffer"); pglReadPixels = (GLREADPIXELSPROC) GetProcAddress(hGL, "glReadPixels"); pglGetError = (GLGETERRORPROC) GetProcAddress(hGL, "glGetError"); pwglSwapLayerBuffers= (WGLSWAPLAYERBUFFERSPROC) GetProcAddress(hGL, "wglSwapLayerBuffers"); pwglDeleteContext = (WGLDELETECONTEXTPROC) GetProcAddress(hGL, "wglDeleteContext"); pwglGetProcAddress = (WGLGETPROCADDRESSPROC) GetProcAddress(hGL, "wglGetProcAddress"); pwglMakeCurrent = (WGLMAKECURRENTPROC) GetProcAddress(hGL, "wglMakeCurrent"); pwglCreateContext = (WGLCREATECONTEXTPROC) GetProcAddress(hGL, "wglCreateContext"); if( !pglReadBuffer || !pglReadPixels || !pglGetError || !pwglSwapLayerBuffers || !pwglDeleteContext || !pwglGetProcAddress || !pwglMakeCurrent || !pwglCreateContext) { return false; } HDC hDC = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL); if(hDC) { PIXELFORMATDESCRIPTOR pfd; ZeroMemory(&pfd, sizeof(pfd)); pfd.nSize = sizeof(pfd); pfd.nVersion = 1; pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; pfd.iPixelType = PFD_TYPE_RGBA; pfd.cColorBits = 32; pfd.cDepthBits = 32; pfd.cAccumBits = 32; pfd.iLayerType = PFD_MAIN_PLANE; SetPixelFormat(hDC, ChoosePixelFormat(hDC, &pfd), &pfd); HGLRC hGlrc = jimglCreateContext(hDC); if(hGlrc) { jimglMakeCurrent(hDC, hGlrc); pglBufferData = (GLBUFFERDATAARBPROC) jimglGetProcAddress("glBufferData"); pglDeleteBuffers = (GLDELETEBUFFERSARBPROC) jimglGetProcAddress("glDeleteBuffers"); pglGenBuffers = (GLGENBUFFERSARBPROC) jimglGetProcAddress("glGenBuffers"); pglMapBuffer = (GLMAPBUFFERPROC) jimglGetProcAddress("glMapBuffer"); pglUnmapBuffer = (GLUNMAPBUFFERPROC) jimglGetProcAddress("glUnmapBuffer"); pglBindBuffer = (GLBINDBUFFERPROC) jimglGetProcAddress("glBindBuffer"); UINT lastErr = GetLastError(); if(pglBufferData && pglDeleteBuffers && pglGenBuffers && pglMapBuffer && pglUnmapBuffer && pglBindBuffer) { glHookSwapBuffers.Hook((FARPROC)SwapBuffers, (FARPROC)SwapBuffersHook); glHookSwapLayerBuffers.Hook((FARPROC)jimglSwapLayerBuffers, (FARPROC)wglSwapLayerBuffersHook); glHookDeleteContext.Hook((FARPROC)jimglDeleteContext, (FARPROC)wglDeleteContextHook); bSuccess = true; } jimglMakeCurrent(NULL, NULL); jimglDeleteContext(hGlrc); if(bSuccess) { glHookSwapBuffers.Rehook(); glHookSwapLayerBuffers.Rehook(); glHookDeleteContext.Rehook(); } } DeleteDC(hDC); } } return bSuccess; }
bool InitDDrawCapture() { bool versionSupported = false; HMODULE hDDrawLib = NULL; if (hDDrawLib = GetModuleHandle(TEXT("ddraw.dll"))) { bool isWinVistaMin = IsWindowsVistaOrGreater(); bool isWin7min = IsWindows7OrGreater(); bool isWin8min = IsWindows8OrGreater(); UPARAM libBaseAddr = UPARAM(hDDrawLib); UPARAM surfCreateOffset; UPARAM surfUnlockOffset; UPARAM surfReleaseOffset; UPARAM surfRestoreOffset; UPARAM surfBltOffset; UPARAM surfFlipOffset; UPARAM surfSetPaletteOffset; UPARAM palSetEntriesOffset; if (isWinVistaMin) { if (!isWin7min) { RUNEVERYRESET logOutput << CurrentTimeString() << "Windows Vista not supported yet" << endl; } else if (isWin7min && !isWin8min) { surfCreateOffset = 0x617E; surfUnlockOffset = 0x4C40; surfReleaseOffset = 0x3239; surfRestoreOffset = 0x3E9CB; surfBltOffset = surfCreateOffset + 0x44F63; surfFlipOffset = surfCreateOffset + 0x37789; surfSetPaletteOffset = surfCreateOffset + 0x4D2D3; palSetEntriesOffset = surfCreateOffset + 0x4CE68; versionSupported = true; } else if (isWin8min) { surfCreateOffset = 0x9530 + 0xC00; surfUnlockOffset = surfCreateOffset + 0x2A1D0; surfReleaseOffset = surfCreateOffset - 0x1A80; surfRestoreOffset = surfCreateOffset + 0x36000; surfBltOffset = surfCreateOffset + 0x438DC; surfFlipOffset = surfCreateOffset + 0x33EF3; surfSetPaletteOffset = surfCreateOffset + 0x4D3B8; palSetEntriesOffset = surfCreateOffset + 0x4CF4C; versionSupported = false; // some crash bugs remaining RUNEVERYRESET logOutput << CurrentTimeString() << "Windows 8 not supported yet" << endl; } else { RUNEVERYRESET logOutput << CurrentTimeString() << "Unknown OS version" << endl; } } else { RUNEVERYRESET logOutput << CurrentTimeString() << "OS version not supported" << endl; } if (versionSupported) { ddrawSurfaceCreate.Hook((FARPROC)(libBaseAddr + surfCreateOffset), (FARPROC)CreateSurface); ddrawSurfaceRestore.Hook((FARPROC)(libBaseAddr + surfRestoreOffset), (FARPROC)Restore); ddrawSurfaceRelease.Hook((FARPROC)(libBaseAddr + surfReleaseOffset), (FARPROC)Release); ddrawSurfaceUnlock.Hook((FARPROC)(libBaseAddr + surfUnlockOffset), (FARPROC)Unlock); ddrawSurfaceBlt.Hook((FARPROC)(libBaseAddr + surfBltOffset), (FARPROC)Blt); ddrawSurfaceFlip.Hook((FARPROC)(libBaseAddr + surfFlipOffset), (FARPROC)Flip); ddrawSurfaceSetPalette.Hook((FARPROC)(libBaseAddr + surfSetPaletteOffset), (FARPROC)SetPalette); ddrawPaletteSetEntries.Hook((FARPROC)(libBaseAddr + palSetEntriesOffset), (FARPROC)PaletteSetEntries); ddrawSurfaceUnlock.Rehook(); ddrawSurfaceFlip.Rehook(); ddrawSurfaceBlt.Rehook(); /* ddrawSurfaceCreate.Rehook(); ddrawSurfaceRestore.Rehook(); ddrawSurfaceRelease.Rehook(); ddrawSurfaceSetPalette.Rehook(); ddrawPaletteSetEntries.Rehook(); */ } } return versionSupported; }
bool InitD3D11Capture() { bool bSuccess = false; HMODULE hD3D11Dll = GetModuleHandle(TEXT("d3d11.dll")); if(hD3D11Dll) { D3D11CREATEPROC d3d11Create = (D3D11CREATEPROC)GetProcAddress(hD3D11Dll, "D3D11CreateDeviceAndSwapChain"); if(d3d11Create) { DXGI_SWAP_CHAIN_DESC swapDesc; ZeroMemory(&swapDesc, sizeof(swapDesc)); swapDesc.BufferCount = 2; swapDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; swapDesc.BufferDesc.Width = 2; swapDesc.BufferDesc.Height = 2; swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapDesc.OutputWindow = hwndSender; swapDesc.SampleDesc.Count = 1; swapDesc.Windowed = TRUE; IDXGISwapChain *swap; ID3D11Device *device; ID3D11DeviceContext *context; D3D_FEATURE_LEVEL desiredLevels[6] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3, D3D_FEATURE_LEVEL_9_2, D3D_FEATURE_LEVEL_9_1, }; D3D_FEATURE_LEVEL receivedLevel; HRESULT hErr; if(SUCCEEDED(hErr = (*d3d11Create)(NULL, D3D_DRIVER_TYPE_NULL, NULL, 0, desiredLevels, 6, D3D11_SDK_VERSION, &swapDesc, &swap, &device, &receivedLevel, &context))) { bSuccess = true; UPARAM *vtable = *(UPARAM**)swap; gi11swapPresent.Hook((FARPROC)*(vtable+(32/4)), (FARPROC)D3D11SwapPresentHook); gi11swapResizeBuffers.Hook((FARPROC)*(vtable+(52/4)), (FARPROC)D3D11SwapResizeBuffersHook); SafeRelease(swap); SafeRelease(device); SafeRelease(context); gi11swapPresent.Rehook(); gi11swapResizeBuffers.Rehook(); } else { RUNONCE logOutput << "InitD3D11Capture: D3D11CreateDeviceAndSwapChain definitely failed, result = " << UINT(hErr) << endl; } } else { RUNONCE logOutput << "InitD3D11Capture: could not get address of D3D11CreateDeviceAndSwapChain" << endl; } } return bSuccess; }
bool InitGLCapture() { static HWND hwndOpenGLSetupWindow = NULL; bool bSuccess = false; if(!hwndOpenGLSetupWindow) { WNDCLASSEX windowClass; ZeroMemory(&windowClass, sizeof(windowClass)); windowClass.cbSize = sizeof(windowClass); windowClass.style = CS_OWNDC; windowClass.lpfnWndProc = DefWindowProc; windowClass.lpszClassName = TEXT("OBSOGLHookClass"); windowClass.hInstance = hinstMain; if(RegisterClassEx(&windowClass)) { hwndOpenGLSetupWindow = CreateWindowEx (0, TEXT("OBSOGLHookClass"), TEXT("OBS OpenGL Context Window"), WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, 0, 1, 1, NULL, NULL, hinstMain, NULL ); } } HMODULE hGL = GetModuleHandle(TEXT("opengl32.dll")); if(hGL && hwndOpenGLSetupWindow) { pglReadBuffer = (GLREADBUFFERPROC) GetProcAddress(hGL, "glReadBuffer"); pglReadPixels = (GLREADPIXELSPROC) GetProcAddress(hGL, "glReadPixels"); pglGetError = (GLGETERRORPROC) GetProcAddress(hGL, "glGetError"); pwglSwapLayerBuffers= (WGLSWAPLAYERBUFFERSPROC) GetProcAddress(hGL, "wglSwapLayerBuffers"); pwglSwapBuffers= (WGLSWAPBUFFERSPROC) GetProcAddress(hGL, "wglSwapBuffers"); pwglDeleteContext = (WGLDELETECONTEXTPROC) GetProcAddress(hGL, "wglDeleteContext"); pwglGetProcAddress = (WGLGETPROCADDRESSPROC) GetProcAddress(hGL, "wglGetProcAddress"); pwglMakeCurrent = (WGLMAKECURRENTPROC) GetProcAddress(hGL, "wglMakeCurrent"); pwglCreateContext = (WGLCREATECONTEXTPROC) GetProcAddress(hGL, "wglCreateContext"); if( !pglReadBuffer || !pglReadPixels || !pglGetError || !pwglSwapLayerBuffers || !pwglSwapBuffers || !pwglDeleteContext || !pwglGetProcAddress || !pwglMakeCurrent || !pwglCreateContext) { return false; } HDC hDC = GetDC(hwndOpenGLSetupWindow); if(hDC) { PIXELFORMATDESCRIPTOR pfd; ZeroMemory(&pfd, sizeof(pfd)); pfd.nSize = sizeof(pfd); pfd.nVersion = 1; pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_GENERIC_ACCELERATED; pfd.iPixelType = PFD_TYPE_RGBA; pfd.cColorBits = 32; pfd.cDepthBits = 32; pfd.cAccumBits = 32; pfd.iLayerType = PFD_MAIN_PLANE; SetPixelFormat(hDC, ChoosePixelFormat(hDC, &pfd), &pfd); HGLRC hGlrc = jimglCreateContext(hDC); if(hGlrc) { jimglMakeCurrent(hDC, hGlrc); pglBufferData = (GLBUFFERDATAARBPROC) jimglGetProcAddress("glBufferData"); pglDeleteBuffers = (GLDELETEBUFFERSARBPROC) jimglGetProcAddress("glDeleteBuffers"); pglGenBuffers = (GLGENBUFFERSARBPROC) jimglGetProcAddress("glGenBuffers"); pglMapBuffer = (GLMAPBUFFERPROC) jimglGetProcAddress("glMapBuffer"); pglUnmapBuffer = (GLUNMAPBUFFERPROC) jimglGetProcAddress("glUnmapBuffer"); pglBindBuffer = (GLBINDBUFFERPROC) jimglGetProcAddress("glBindBuffer"); UINT lastErr = GetLastError(); if(pglBufferData && pglDeleteBuffers && pglGenBuffers && pglMapBuffer && pglUnmapBuffer && pglBindBuffer) { glHookSwapBuffers.Hook((FARPROC)SwapBuffers, (FARPROC)SwapBuffersHook); glHookSwapLayerBuffers.Hook((FARPROC)jimglSwapLayerBuffers, (FARPROC)wglSwapLayerBuffersHook); glHookwglSwapBuffers.Hook((FARPROC)jimglSwapBuffers, (FARPROC)wglSwapBuffersHook); glHookDeleteContext.Hook((FARPROC)jimglDeleteContext, (FARPROC)wglDeleteContextHook); bSuccess = true; } jimglMakeCurrent(NULL, NULL); jimglDeleteContext(hGlrc); ReleaseDC(hwndOpenGLSetupWindow, hDC); if(bSuccess) { glHookSwapBuffers.Rehook(); glHookSwapLayerBuffers.Rehook(); glHookwglSwapBuffers.Rehook(); glHookDeleteContext.Rehook(); DestroyWindow(hwndOpenGLSetupWindow); hwndOpenGLSetupWindow = NULL; UnregisterClass(TEXT("OBSOGLHookClass"), hinstMain); } } if(hwndOpenGLSetupWindow) ReleaseDC(hwndOpenGLSetupWindow, hDC); } } return bSuccess; }