Пример #1
0
void SetupD3D11(IDXGISwapChain *swapChain)
{
    ClearD3D11Data();

    DXGI_SWAP_CHAIN_DESC scd;
    if(SUCCEEDED(swapChain->GetDesc(&scd)))
    {
        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 )
            {
                dxgiFormat = scd.BufferDesc.Format;
                d3d11CaptureInfo.cx = scd.BufferDesc.Width;
                d3d11CaptureInfo.cy = scd.BufferDesc.Height;
                d3d11CaptureInfo.hwndCapture = scd.OutputWindow;
                bIsMultisampled = scd.SampleDesc.Count > 1;
            }
        }
    }

    lastTime = 0;
    OSInitializeTimer();
}
Пример #2
0
void SetupD3D101(IDXGISwapChain *swapChain)
{
    logOutput << CurrentTimeString() << "setting up d3d10.1 data" << endl;
    ClearD3D101Data();

    DXGI_SWAP_CHAIN_DESC scd;
    if(SUCCEEDED(swapChain->GetDesc(&scd)))
    {
        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 ||
                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 << CurrentTimeString() << "found dxgi format (dx10.1) of: " << UINT(dxgiFormat) <<
                    ", size: {" << scd.BufferDesc.Width << ", " << scd.BufferDesc.Height <<
                    "}, multisampled: " << (bIsMultisampled ? "true" : "false") << endl;
            }
        }
    }

    lastTime = 0;
    OSInitializeTimer();
}
Пример #3
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();
            }
        }
    }
}
Пример #4
0
bool SetupDDraw()
{
    logOutput << CurrentTimeString() << "called SetupDDraw()" << endl;

    if (!g_ddInterface)
    {
        logOutput << CurrentTimeString() << "SetupDDraw: DirectDraw interface not set, returning" << endl;
        return false;
    }

    bool bSuccess = true;

    bKillThread = false;

    if (hCopyThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CopyDDrawTextureThread, NULL, 0, NULL))
    {
        if (!(hCopyEvent = CreateEvent(NULL, FALSE, FALSE, NULL)))
        {
            logOutput << CurrentTimeString() << "SetupDDraw: CreateEvent failed, GetLastError = " << GetLastError() << endl;
            bSuccess = false;
        }
    }
    else
    {
        logOutput << CurrentTimeString() << "SetupDDraw: CreateThread failed, GetLastError = " << GetLastError() << endl;
        bSuccess = false;
    }

    if (bSuccess)
    {
        if (!ddUnlockFctMutex)
        {
            ddUnlockFctMutex = CreateMutex(NULL, FALSE, mutexName);
            if (!ddUnlockFctMutex)
            {
                RUNEVERYRESET logOutput << CurrentTimeString() << "SetupDDraw: CreateMutex failed, GetLastError = " << GetLastError() << endl;
                bSuccess = false;
            }
        }
    }

    if (bSuccess && !g_frontSurface)
    {
        RUNEVERYRESET logOutput << "SetupDDraw: frontSurface and surface descriptor not set, returning" << endl;
        CleanUpDDraw();
        return false;
    }
    else if (bSuccess)
    {
        LPDIRECTDRAWPALETTE palette = NULL;
        HRESULT err;
        if (SUCCEEDED(err = g_frontSurface->GetPalette(&palette)))
        {
            if (palette)
                SetupPalette(palette);
        }
        else if (err == DDERR_NOPALETTEATTACHED)
        {
            //logOutput << CurrentTimeString() << "No palette attached to primary surface" << endl;
        }
        else
        {
            logOutput << CurrentTimeString() << "Error retrieving palette" << endl;
            printDDrawError(err, "getFrontSurface");
        }
    }

    if (bSuccess && !g_surfaceDesc)
    {
        logOutput << CurrentTimeString() << "SetupDDraw: no surface descriptor found, creating a new one (not an error)" << endl;

        g_surfaceDesc = new DDSURFACEDESC2;
        g_surfaceDesc->dwSize = sizeof(DDSURFACEDESC);

        HRESULT hr;
        if (FAILED(hr = ((LPDIRECTDRAWSURFACE)g_frontSurface)->GetSurfaceDesc((LPDDSURFACEDESC)g_surfaceDesc)))
        {
            g_surfaceDesc->dwSize = sizeof(DDSURFACEDESC2);
            if (FAILED(g_frontSurface->GetSurfaceDesc(g_surfaceDesc)))
            {
                logOutput << CurrentTimeString() << "SetupDDraw: error getting surface descriptor" << endl;
                printDDrawError(hr, "SetupDDraw");
                bSuccess = false;
            }
        }
    }

    if (bSuccess && g_surfaceDesc)
    {
        const DDPIXELFORMAT& pf = g_surfaceDesc->ddpfPixelFormat;
        if (pf.dwFlags & DDPF_RGB)
        {
            if (pf.dwRGBBitCount == 16)
            {
                logOutput << CurrentTimeString() << "SetupDDraw: found 16bit format (using R5G6B5 conversion)" << endl;
                g_bConvert16to32 = true;
            }
            else if (pf.dwRGBBitCount == 32)
            {
                logOutput << CurrentTimeString() << "SetupDDraw: found 32bit format (using plain copy)" << endl;
                g_bUse32bitCapture = true;
            }
        }
        else if (pf.dwFlags & (DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED2 | DDPF_PALETTEINDEXED1))
        {
            logOutput << CurrentTimeString() << "SetupDDraw: front surface uses palette indices" << endl;
        }
    }

    if (bSuccess)
    {
        logOutput << CurrentTimeString() << "SetupDDraw: primary surface width = " << g_surfaceDesc->dwWidth << ", height = " << g_surfaceDesc->dwHeight << endl;
        g_dwSize = g_surfaceDesc->lPitch*g_surfaceDesc->dwHeight;
        ddrawCaptureInfo.captureType = CAPTURETYPE_MEMORY;
        ddrawCaptureInfo.cx = g_surfaceDesc->dwWidth;
        ddrawCaptureInfo.cy = g_surfaceDesc->dwHeight;
        ddrawCaptureInfo.pitch = 4 * ddrawCaptureInfo.cx;
        ddrawCaptureInfo.hwndCapture = (DWORD)hwndSender;
        ddrawCaptureInfo.format = GS_BGRA;
        DWORD g_dwCaptureSize = ddrawCaptureInfo.pitch*ddrawCaptureInfo.cy;
        ddrawCaptureInfo.bFlip = FALSE;
        ddrawCaptureInfo.mapID = InitializeSharedMemoryCPUCapture(g_dwCaptureSize, &ddrawCaptureInfo.mapSize, &copyData, textureBuffers);

        memcpy(infoMem, &ddrawCaptureInfo, sizeof(CaptureInfo));

        DDSURFACEDESC2 captureDesc;
        ZeroMemory(&captureDesc, sizeof(captureDesc));
        captureDesc.dwSize = sizeof(DDSURFACEDESC2);

        captureDesc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_PITCH;
        captureDesc.dwWidth = g_surfaceDesc->dwWidth;
        captureDesc.dwHeight = g_surfaceDesc->dwHeight;
        captureDesc.lPitch = g_surfaceDesc->lPitch;
        captureDesc.ddpfPixelFormat = g_surfaceDesc->ddpfPixelFormat;
        captureDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;

        HRESULT err;

        ddrawSurfaceCreate.Unhook();
        for (int i = 0; i < NUM_BUFFERS && bSuccess; i++)
        {
            if (FAILED(err = g_ddInterface->CreateSurface(&captureDesc, &ddCaptures[i], NULL)))
            {
                logOutput << CurrentTimeString() << "SetupDDraw: Could not create offscreen capture" << endl;
                printDDrawError(err, "SetupDDraw");
                bSuccess = false;
                break;
            }
        }
        ddrawSurfaceCreate.Rehook();

        if (bSuccess)
        {
            bHasTextures = true;

            SetEvent(hSignalReady);

            OSInitializeTimer();
        }
    }

    if (bSuccess)
    {
        logOutput << CurrentTimeString() << "SetupDDraw successfull" << endl;
        HookAll();
        return true;
    }
    else
    {
        logOutput << CurrentTimeString() << "SetupDDraw failed" << endl;
        CleanUpDDraw();
        return false;
    }
}
Пример #5
0
void DoGLCPUHook(RECT &rc)
{
    glcaptureInfo.cx = rc.right;
    glcaptureInfo.cy = rc.bottom;

    glGenBuffers(NUM_BUFFERS, gltextures);

    DWORD dwSize = glcaptureInfo.cx*glcaptureInfo.cy*4;

    BOOL bSuccess = true;
    for(UINT i=0; i<NUM_BUFFERS; i++)
    {
        UINT test = 0;

        glBindBuffer(GL_PIXEL_PACK_BUFFER, gltextures[i]);
        glBufferData(GL_PIXEL_PACK_BUFFER, dwSize, 0, GL_STREAM_READ);

        if(!(glDataMutexes[i] = OSCreateMutex()))
        {
            logOutput << CurrentTimeString() << "DoGLCPUHook: OSCreateMutex " << i << " failed, GetLastError = " << GetLastError();
            bSuccess = false;
            break;
        }
    }

    glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);

    if(bSuccess)
    {
        bKillThread = false;

        if(hCopyThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CopyGLCPUTextureThread, NULL, 0, NULL))
        {
            if(!(hCopyEvent = CreateEvent(NULL, FALSE, FALSE, NULL)))
            {
                logOutput << CurrentTimeString() << "DoGLCPUHook: CreateEvent failed, GetLastError = " << GetLastError();
                bSuccess = false;
            }
        }
        else
        {
            logOutput << CurrentTimeString() << "DoGLCPUHook: CreateThread failed, GetLastError = " << GetLastError();
            bSuccess = false;
        }
    }

    if(bSuccess)
    {
        glcaptureInfo.mapID = InitializeSharedMemoryCPUCapture(dwSize, &glcaptureInfo.mapSize, &copyData, textureBuffers);
        if(!glcaptureInfo.mapID)
            bSuccess = false;
    }

    if(bSuccess)
    {
        bHasTextures = true;
        glcaptureInfo.captureType = CAPTURETYPE_MEMORY;
        glcaptureInfo.hwndCapture = (DWORD)hwndTarget;
        glcaptureInfo.pitch = glcaptureInfo.cx*4;
        glcaptureInfo.bFlip = TRUE;

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

        logOutput << CurrentTimeString() << "DoGLCPUHook: success" << endl;

        OSInitializeTimer();
    }
    else
        ClearGLData();
}