Exemple #1
0
HRESULT STDMETHODCALLTYPE D3D11SwapPresentHook(IDXGISwapChain *swap, UINT syncInterval, UINT flags)
{
    if(lpCurrentSwap == NULL && !bTargetAcquired)
    {
        lpCurrentSwap = swap;
        SetupD3D11(swap);
        bTargetAcquired = true;
    }

    if(lpCurrentSwap == swap)
    {
        ID3D11Device *device = NULL;
        HRESULT chi;
        if(SUCCEEDED(chi = swap->GetDevice(__uuidof(ID3D11Device), (void**)&device)))
        {
            if(!lpCurrentDevice)
            {
                lpCurrentDevice = device;

                /*FARPROC curRelease = GetVTable(device, (8/4));
                if(curRelease != newD3D11Release)
                {
                    oldD3D11Release = curRelease;
                    newD3D11Release = (FARPROC)DeviceReleaseHook;
                    SetVTable(device, (8/4), newD3D11Release);
                }*/
            }

            ID3D11DeviceContext *context;
            device->GetImmediateContext(&context);

            if(bCapturing && bStopRequested)
            {
                ClearD3D11Data();
                bStopRequested = false;
            }

            if(!bHasTextures && bCapturing)
            {
                if(dxgiFormat)
                {
                    if(!hwndReceiver)
                        hwndReceiver = FindWindow(RECEIVER_WINDOWCLASS, NULL);

                    if(hwndReceiver)
                    {
                        BOOL bSuccess = DoD3D11Hook(device);

                        if(bSuccess)
                        {
                            d3d11CaptureInfo.mapID = InitializeSharedMemoryGPUCapture(&texData);
                            if(!d3d11CaptureInfo.mapID)
                            {
                                RUNONCE logOutput << "SwapPresentHook: creation of shared memory failed" << endl;
                                bSuccess = false;
                            }
                        }

                        if(bSuccess)
                            bSuccess = IsWindow(hwndReceiver);

                        if(bSuccess)
                        {
                            bHasTextures = true;
                            d3d11CaptureInfo.captureType = CAPTURETYPE_SHAREDTEX;
                            d3d11CaptureInfo.hwndSender = hwndSender;
                            d3d11CaptureInfo.bFlip = FALSE;
                            texData->texHandles[0] = sharedHandles[0];
                            texData->texHandles[1] = sharedHandles[1];
                            PostMessage(hwndReceiver, RECEIVER_NEWCAPTURE, 0, (LPARAM)&d3d11CaptureInfo);

                            logOutput << "DoD3D11Hook: success";
                        }
                        else
                        {
                            ClearD3D11Data();
                        }
                    }
                }
            }

            if(bHasTextures)
            {
                LONGLONG frameTime;
                if(bCapturing)
                {
                    if(texData)
                    {
                        if(frameTime = texData->frameTime)
                        {
                            LONGLONG timeVal = OSGetTimeMicroseconds();
                            LONGLONG timeElapsed = timeVal-lastTime;

                            if(timeElapsed >= frameTime)
                            {
                                lastTime += frameTime;
                                if(timeElapsed > frameTime*2)
                                    lastTime = timeVal;

                                DWORD nextCapture = curCapture == 0 ? 1 : 0;

                                ID3D11Resource *backBuffer = NULL;

                                if(SUCCEEDED(swap->GetBuffer(0, IID_ID3D11Resource, (void**)&backBuffer)))
                                {
                                    if(bIsMultisampled)
                                        context->ResolveSubresource(copyTextureGame, 0, backBuffer, 0, dxgiFormat);
                                    else
                                        context->CopyResource(copyTextureGame, backBuffer);

                                    ID3D10Texture2D *outputTexture = NULL;
                                    int lastRendered = -1;

                                    if(keyedMutexes[curCapture]->AcquireSync(0, 0) == WAIT_OBJECT_0)
                                        lastRendered = (int)curCapture;
                                    else if(keyedMutexes[nextCapture]->AcquireSync(0, 0) == WAIT_OBJECT_0)
                                        lastRendered = (int)nextCapture;

                                    if(lastRendered != -1)
                                    {
                                        shareDevice->CopyResource(sharedTextures[lastRendered], copyTextureIntermediary);
                                        keyedMutexes[lastRendered]->ReleaseSync(0);
                                    }

                                    texData->lastRendered = lastRendered;
                                    backBuffer->Release();
                                }

                                curCapture = nextCapture;
                            }
                        }
                    }
                }
                else
                    ClearD3D11Data();
            }

            device->Release();
            context->Release();
        }
    }

    gi11swapPresent.Unhook();
    HRESULT hRes = swap->Present(syncInterval, flags);
    gi11swapPresent.Rehook();

    return hRes;
}
Exemple #2
0
void DoD3D11Capture(IDXGISwapChain *swap)
{
    ID3D11Device *device = NULL;
    HRESULT chi;
    if(SUCCEEDED(chi = swap->GetDevice(__uuidof(ID3D11Device), (void**)&device)))
    {
        if(!lpCurrentDevice)
        {
            lpCurrentDevice = device;

            /*FARPROC curRelease = GetVTable(device, (8/4));
            if(curRelease != newD3D11Release)
            {
                oldD3D11Release = curRelease;
                newD3D11Release = (FARPROC)DeviceReleaseHook;
                SetVTable(device, (8/4), newD3D11Release);
            }*/
        }

        ID3D11DeviceContext *context;
        device->GetImmediateContext(&context);

        if(bCapturing && bStopRequested)
        {
            ClearD3D11Data();
            bCapturing = false;
            bStopRequested = false;
        }

        if(!bCapturing && WaitForSingleObject(hSignalRestart, 0) == WAIT_OBJECT_0)
        {
            hwndOBS = FindWindow(OBS_WINDOW_CLASS, NULL);
            if(hwndOBS)
                bCapturing = true;
        }

        if(!bHasTextures && bCapturing)
        {
            if(dxgiFormat && hwndOBS)
            {
                BOOL bSuccess = DoD3D11Hook(device);

                if(bSuccess)
                {
                    d3d11CaptureInfo.mapID = InitializeSharedMemoryGPUCapture(&texData);
                    if(!d3d11CaptureInfo.mapID)
                    {
                        RUNONCE logOutput << "SwapPresentHook: creation of shared memory failed" << endl;
                        bSuccess = false;
                    }
                }

                if(bSuccess)
                {
                    bHasTextures = true;
                    d3d11CaptureInfo.captureType = CAPTURETYPE_SHAREDTEX;
                    d3d11CaptureInfo.bFlip = FALSE;
                    texData->texHandle = (DWORD)sharedHandle;

                    memcpy(infoMem, &d3d11CaptureInfo, sizeof(CaptureInfo));
                    SetEvent(hSignalReady);

                    logOutput << "DoD3D11Hook: success" << endl;
                }
                else
                {
                    ClearD3D11Data();
                }
            }
        }

        if(bHasTextures)
        {
            LONGLONG timeVal = OSGetTimeMicroseconds();

            //check keep alive state, dumb but effective
            if(bCapturing)
            {
                if((timeVal-keepAliveTime) > 3000000)
                {
                    HANDLE hKeepAlive = OpenEvent(EVENT_ALL_ACCESS, FALSE, strKeepAlive.c_str());
                    if (hKeepAlive) {
                        CloseHandle(hKeepAlive);
                    } else {
                        ClearD3D11Data();
                        bCapturing = false;
                    }

                    keepAliveTime = timeVal;
                }
            }

            LONGLONG frameTime;
            if(bCapturing)
            {
                if(texData)
                {
                    if(frameTime = texData->frameTime)
                    {
                        LONGLONG timeElapsed = timeVal-lastTime;

                        if(timeElapsed >= frameTime)
                        {
                            if(!IsWindow(hwndOBS))
                            {
                                hwndOBS = NULL;
                                bStopRequested = true;
                            }

                            if(WaitForSingleObject(hSignalEnd, 0) == WAIT_OBJECT_0)
                                bStopRequested = true;

                            lastTime += frameTime;
                            if(timeElapsed > frameTime*2)
                                lastTime = timeVal;

                            DWORD nextCapture = curCapture == 0 ? 1 : 0;

                            ID3D11Resource *backBuffer = NULL;

                            if(SUCCEEDED(swap->GetBuffer(0, IID_ID3D11Resource, (void**)&backBuffer)))
                            {
                                if(bIsMultisampled)
                                    context->ResolveSubresource(copyTextureGame, 0, backBuffer, 0, dxgiFormat);
                                else
                                    context->CopyResource(copyTextureGame, backBuffer);

                                backBuffer->Release();
                            }

                            curCapture = nextCapture;
                        }
                    }
                }
            }
            else
                ClearD3D11Data();
        }

        device->Release();
        context->Release();
    }
}
Exemple #3
0
void CaptureDDraw()
{
    //RUNEVERYRESET logOutput << CurrentTimeString() << "called CaptureDDraw()" << endl;

    if (bCapturing && WaitForSingleObject(hSignalEnd, 0) == WAIT_OBJECT_0)
    {
        //logOutput << CurrentTimeString() << "not capturing or received hSignalEnd" << endl;
        bStopRequested = true;
    }

    if (bCapturing && !IsWindow(hwndOBS))
    {
        //logOutput << CurrentTimeString() << "not capturing or OBS window not found" << endl;
        hwndOBS = NULL;
        bStopRequested = true;
    }

    if (bStopRequested)
    {
        CleanUpDDraw();
        bCapturing = false;
        bStopRequested = false;
    }

    if (!bCapturing && WaitForSingleObject(hSignalRestart, 0) == WAIT_OBJECT_0)
    {
        //logOutput << CurrentTimeString() << "capturing and received hSignalRestart" << endl;
        hwndOBS = FindWindow(OBS_WINDOW_CLASS, NULL);
        if (hwndOBS) {
            logOutput << CurrentTimeString() << "received restart event, capturing" << endl;
            bCapturing = true;
        }
        else {
            logOutput << CurrentTimeString() << "received restart event, but couldn't find window" << endl;
        }
    }

    LONGLONG timeVal = OSGetTimeMicroseconds();

    //check keep alive state, dumb but effective
    if (bCapturing)
    {
        if (!keepAliveTime)
            keepAliveTime = timeVal;

        if ((timeVal - keepAliveTime) > 5000000)
        {
            HANDLE hKeepAlive = OpenEvent(EVENT_ALL_ACCESS, FALSE, strKeepAlive.c_str());
            if (hKeepAlive) {
                CloseHandle(hKeepAlive);
            }
            else {
                logOutput << CurrentTimeString() << "Keepalive no longer found on ddraw, freeing capture data" << endl;
                CleanUpDDraw();
                bCapturing = false;
            }

            keepAliveTime = timeVal;
        }
    }

    if (bHasTextures)
    {
        LONGLONG frameTime;
        if (bCapturing)
        {
            if (copyData)
            {
                if (frameTime = copyData->frameTime)
                {
                    LONGLONG timeElapsed = timeVal - lastTime;

                    if (timeElapsed >= frameTime)
                    {
                        lastTime += frameTime;
                        if (timeElapsed > frameTime * 2)
                            lastTime = timeVal;


                        //logOutput << CurrentTimeString() << "CaptureDDraw: capturing screen from 0x" << g_frontSurface << endl;

                        HRESULT hr;
                        ddrawSurfaceBlt.Unhook();
                        hr = ddCaptures[curCapture]->Blt(NULL, g_frontSurface, NULL, DDBLT_ASYNC, NULL);
                        ddrawSurfaceBlt.Rehook();
                        if (SUCCEEDED(hr))
                        {
                            DWORD nextCapture = (curCapture == NUM_BUFFERS - 1) ? 0 : (curCapture + 1);
                            curCPUTexture = curCapture;
                            curCapture = nextCapture;

                            SetEvent(hCopyEvent);
                        }
                        else
                        {
                            printDDrawError(hr, "CaptureDDraw");
                        }
                        //logOutput << CurrentTimeString() << "CaptureDDraw: finished capturing" << endl;
                    }
                }
            }
        }
    }
}
Exemple #4
0
void DoD3D101Capture(IDXGISwapChain *swap)
{
    HRESULT hRes;

    ID3D10Device *device = NULL;
    if(SUCCEEDED(swap->GetDevice(__uuidof(ID3D10Device), (void**)&device)))
    {
        if(bCapturing && WaitForSingleObject(hSignalEnd, 0) == WAIT_OBJECT_0)
            bStopRequested = true;

        if(bCapturing && !IsWindow(hwndOBS))
        {
            hwndOBS = NULL;
            bStopRequested = true;
        }

        if(!lpCurrentDevice)
        {
            lpCurrentDevice = device;

            /*FARPROC oldRelease = GetVTable(device, (8/4));
            if(oldRelease != newD3D10Release)
            {
                oldD3D10Release = oldRelease;
                newD3D10Release = ConvertClassProcToFarproc((CLASSPROC)&D3D101Override::DeviceReleaseHook);
                SetVTable(device, (8/4), newD3D10Release);
            }*/
        }

        if(bCapturing && bStopRequested)
        {
            RUNEVERYRESET logOutput << CurrentTimeString() << "stop requested, terminating d3d10.1 capture" << endl;

            ClearD3D101Data();
            bCapturing = false;
            bStopRequested = false;
        }

        if(!bCapturing && WaitForSingleObject(hSignalRestart, 0) == WAIT_OBJECT_0)
        {
            hwndOBS = FindWindow(OBS_WINDOW_CLASS, NULL);
            if(hwndOBS)
                bCapturing = true;
        }

        if(!bHasTextures && bCapturing)
        {
            if(dxgiFormat && hwndOBS)
            {
                BOOL bSuccess = DoD3D101Hook(device);

                if(bSuccess)
                {
                    d3d101CaptureInfo.mapID = InitializeSharedMemoryGPUCapture(&texData);
                    if(!d3d101CaptureInfo.mapID)
                        bSuccess = false;
                }

                if(bSuccess)
                {
                    bHasTextures = true;
                    d3d101CaptureInfo.captureType = CAPTURETYPE_SHAREDTEX;
                    d3d101CaptureInfo.bFlip = FALSE;
                    texData->texHandle = (DWORD)sharedHandle;

                    memcpy(infoMem, &d3d101CaptureInfo, sizeof(CaptureInfo));
                    SetEvent(hSignalReady);

                    logOutput << CurrentTimeString() << "DoD3D101Hook: success" << endl;
                }
                else
                {
                    ClearD3D101Data();
                }
            }
        }

        LONGLONG timeVal = OSGetTimeMicroseconds();

        //check keep alive state, dumb but effective
        if(bCapturing)
        {
            if (!keepAliveTime)
                keepAliveTime = timeVal;

            if((timeVal-keepAliveTime) > 5000000)
            {
                HANDLE hKeepAlive = OpenEvent(EVENT_ALL_ACCESS, FALSE, strKeepAlive.c_str());
                if (hKeepAlive) {
                    CloseHandle(hKeepAlive);
                } else {
                    ClearD3D101Data();
                    logOutput << CurrentTimeString() << "Keepalive no longer found on d3d10.1, freeing capture data" << endl;
                    bCapturing = false;
                }

                keepAliveTime = timeVal;
            }
        }

        if(bHasTextures)
        {
            LONGLONG frameTime;
            if(bCapturing)
            {
                if(texData)
                {
                    if(frameTime = texData->frameTime)
                    {
                        LONGLONG timeElapsed = timeVal-lastTime;

                        if(timeElapsed >= frameTime)
                        {
                            lastTime += frameTime;
                            if(timeElapsed > frameTime*2)
                                lastTime = timeVal;

                            DWORD nextCapture = curCapture == 0 ? 1 : 0;

                            ID3D10Resource *backBuffer = NULL;
                            if(SUCCEEDED(hRes = swap->GetBuffer(0, IID_ID3D10Resource, (void**)&backBuffer)))
                            {
                                if(bIsMultisampled)
                                    device->ResolveSubresource(copyD3D101TextureGame, 0, backBuffer, 0, dxgiFormat);
                                else
                                    device->CopyResource(copyD3D101TextureGame, backBuffer);

                                RUNEVERYRESET logOutput << CurrentTimeString() << "successfully capturing d3d10.1 frames via GPU" << endl;

                                backBuffer->Release();
                            } else {
                                RUNEVERYRESET logOutput << CurrentTimeString() << "DoD3D101Capture: swap->GetBuffer failed: result = " << UINT(hRes) << endl;
                            }

                            curCapture = nextCapture;
                        }
                    }
                }
            } else {
                RUNEVERYRESET logOutput << CurrentTimeString() << "no longer capturing, terminating d3d10.1 capture" << endl;
                ClearD3D101Data();
            }
        }
    }

    SafeRelease(device);
}
Exemple #5
0
void HandleGLSceneUpdate(HDC hDC)
{
    if(!bTargetAcquired && hdcAcquiredDC == NULL)
    {
        logOutput << CurrentTimeString() << "setting up gl data" << endl;
        PIXELFORMATDESCRIPTOR pfd;

        hwndTarget = WindowFromDC(hDC);

        int pixFormat = GetPixelFormat(hDC);
        DescribePixelFormat(hDC, pixFormat, sizeof(pfd), &pfd);

        if(pfd.cColorBits == 32 && hwndTarget)
        {
            bTargetAcquired = true;
            hdcAcquiredDC = hDC;
            glcaptureInfo.format = GS_BGR;
        }

        OSInitializeTimer();
    }

    if(hDC == hdcAcquiredDC)
    {
        if(bCapturing && WaitForSingleObject(hSignalEnd, 0) == WAIT_OBJECT_0)
            bStopRequested = true;

        if(bCapturing && !IsWindow(hwndOBS))
        {
            hwndOBS = NULL;
            bStopRequested = true;
        }

        if(bCapturing && bStopRequested)
        {
            RUNEVERYRESET logOutput << CurrentTimeString() << "stop requested, terminating gl capture" << endl;

            ClearGLData();
            bCapturing = false;
            bStopRequested = false;
            bReacquiring = false;
        }

        if(!bCapturing && WaitForSingleObject(hSignalRestart, 0) == WAIT_OBJECT_0)
        {
            hwndOBS = FindWindow(OBS_WINDOW_CLASS, NULL);
            if(hwndOBS)
                bCapturing = true;
        }

        RECT rc;
        GetClientRect(hwndTarget, &rc);

        if(bCapturing && bReacquiring)
        {
            if(lastCX != rc.right || lastCY != rc.bottom) //reset if continuing to size within the 3 seconds
            {
                reacquireStart = OSGetTimeMicroseconds();
                lastCX = rc.right;
                lastCY = rc.bottom;
            }

            if(OSGetTimeMicroseconds()-reacquireTime >= 3000000) { //3 second to reacquire
                RUNEVERYRESET logOutput << CurrentTimeString() << "reacquiring gl due to resize..." << endl;
                bReacquiring = false;
            } else {
                return;
            }
        }

        if(bCapturing && (!bHasTextures || rc.right != glcaptureInfo.cx || rc.bottom != glcaptureInfo.cy))
        {
            if (!rc.right || !rc.bottom)
                return;

            if(bHasTextures) //resizing
            {
                ClearGLData();
                bReacquiring = true;
                reacquireStart = OSGetTimeMicroseconds();
                lastCX = rc.right;
                lastCY = rc.bottom;
                return;
            }
            else
            {
                if(hwndOBS)
                    DoGLCPUHook(rc);
                else
                    ClearGLData();
            }
        }

        LONGLONG timeVal = OSGetTimeMicroseconds();

        //check keep alive state, dumb but effective
        if(bCapturing)
        {
            if (!keepAliveTime)
                keepAliveTime = timeVal;

            if((timeVal-keepAliveTime) > 5000000)
            {
                HANDLE hKeepAlive = OpenEvent(EVENT_ALL_ACCESS, FALSE, strKeepAlive.c_str());
                if (hKeepAlive) {
                    CloseHandle(hKeepAlive);
                } else {
                    ClearGLData();
                    logOutput << CurrentTimeString() << "Keepalive no longer found on gl, freeing capture data" << endl;
                    bCapturing = false;
                }

                keepAliveTime = timeVal;
            }
        }

        if(bHasTextures)
        {
            LONGLONG frameTime;
            if(bCapturing)
            {
                if(copyData)
                {
                    if(frameTime = copyData->frameTime)
                    {
                        LONGLONG timeElapsed = timeVal-lastTime;

                        if(timeElapsed >= frameTime)
                        {
                            lastTime += frameTime;
                            if(timeElapsed > frameTime*2)
                                lastTime = timeVal;

                            GLuint texture = gltextures[curCapture];
                            DWORD nextCapture = (curCapture == NUM_BUFFERS-1) ? 0 : (curCapture+1);

                            glReadBuffer(GL_BACK);
                            glBindBuffer(GL_PIXEL_PACK_BUFFER, texture);

                            if(glLockedTextures[curCapture])
                            {
                                OSEnterMutex(glDataMutexes[curCapture]);

                                glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
                                glLockedTextures[curCapture] = false;

                                OSLeaveMutex(glDataMutexes[curCapture]);
                            }

                            glReadPixels(0, 0, glcaptureInfo.cx, glcaptureInfo.cy, GL_BGRA, GL_UNSIGNED_BYTE, 0);

                            //----------------------------------

                            glBindBuffer(GL_PIXEL_PACK_BUFFER, gltextures[nextCapture]);
                            pCopyData = (void*)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
                            if(pCopyData)
                            {
                                curCPUTexture = nextCapture;
                                glLockedTextures[nextCapture] = true;

                                RUNEVERYRESET logOutput << CurrentTimeString() << "successfully capturing gl frames via RAM" << endl;

                                SetEvent(hCopyEvent);
                            } else {
                                RUNEVERYRESET logOutput << CurrentTimeString() << "one or more gl frames failed to capture for some reason" << endl;
                            }

                            //----------------------------------

                            glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);

                            curCapture = nextCapture;
                        }
                    }
                }
            }
            else {
                RUNEVERYRESET logOutput << CurrentTimeString() << "no longer capturing, terminating gl capture" << endl;
                ClearGLData();
            }
        }
    }
}