IDirect3DSurface9的LockRect失败

时间:2017-12-21 18:18:33

标签: c++ locking directx video-capture

我已经挂了IDirect3DDevice9接口的Present方法,我希望能够开始视频捕获。

像这样的作品进行截图

if (GetAsyncKeyState('O') & 1) {
    pDevice->CreateOffscreenPlainSurface((rect.right - rect.left),(rect.bottom - rect.top),D3DFMT_A8R8G8B8,D3DPOOL_SYSTEMMEM,&back_buffer, NULL);
    pDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &back_buffer);
    D3DXSaveSurfaceToFile(L"C:\\screenshot.bmp", D3DXIFF_BMP, back_buffer, 0, NULL );

    IDirect3DSurface9_Release(back_buffer);
}

我似乎无法锁定表面。

HRESULT APIENTRY hook_Present(IDirect3DDevice9* pDevice, const RECT* pSourceRect,const RECT* pDestRect, HWND hDestWindowOverride,const RGNDATA* pDirtyRegion) {
    IDirect3DSurface9*back_buffer;
    D3DDEVICE_CREATION_PARAMETERS cparams;
    RECT rect;
    pDevice->GetCreationParameters(&cparams);
    GetClientRect(cparams.hFocusWindow, &rect);
    if (GetAsyncKeyState('R') & 1) {
        if(dx9Capturing == 0) {
            //Create the AVI file
            // etc code
            dx9Capturing = 1
        }
        else if(dx9Capturing == 1) dx9Capturing = 2; // stop capturing
    }

    if(dx9Capturing == 1) {
        // Capture the current frame
        pDevice->CreateOffscreenPlainSurface((rect.right - rect.left),(rect.bottom - rect.top),D3DFMT_A8R8G8B8,D3DPOOL_SYSTEMMEM,&back_buffer, NULL);
        pDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &back_buffer);
        D3DLOCKED_RECT  lockedRect;
        if(FAILED(back_buffer->LockRect(&lockedRect,&rect,D3DLOCK_READONLY))) {
            MessageBoxA(NULL, "Failed locking the back buffer!", "Error", MB_OK);
            return orig_Present(pDevice, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion);
        }
        for(int i=0;i<rect.bottom;i++)
            {
                memcpy((BYTE*)pBits+(rect.bottom-i-1)*rect.right*BITSPERPIXEL/8,(BYTE*)lockedRect.pBits+i*lockedRect.Pitch,rect.right*BITSPERPIXEL/8);
            }
        back_buffer->UnlockRect();
        pAviFile->AddNewFrame(rect.right,rect.bottom,pBits);
    }

    return orig_Present(pDevice, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion);
}

1 个答案:

答案 0 :(得分:0)

D3DERR_INVALIDCALL表示后台缓冲区的大小不等于监视器的分辨率。例如,当您想要捕获具有以下分辨率(1920 * 1080)的监视器时,必须创建具有相同大小的directX9的后台缓冲区。