无法从后台缓冲区(DirectX9)捕获数据

时间:2012-10-30 09:15:26

标签: c++ visual-studio-2008 visual-c++ gdi directx-9

我正在尝试找到截屏的最快方法。到目前为止,我已经发现可以使用GDI或DirectX。使用GDI我能够在35ms内捕获屏幕,而使用DirectX Front缓冲区则需要73ms的平均值。我想要比这更快的方法。为此,在DirectX中捕获Back Buffer似乎是一种很好的方法。我使用以下代码执行相同的操作:

    D3DDISPLAYMODE  ddm;
    D3DPRESENT_PARAMETERS   d3dpp;

    if((g_pD3D=Direct3DCreate9(D3D_SDK_VERSION))==NULL)
    {
        ErrorMessage("Unable to Create Direct3D ");
        return E_FAIL;
    }

    if(FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&ddm)))
    {
        ErrorMessage("Unable to Get Adapter Display Mode");
        return E_FAIL;
    }

    ZeroMemory(&d3dpp,sizeof(D3DPRESENT_PARAMETERS));

    d3dpp.Windowed=WINDOW_MODE;
    d3dpp.Flags=D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
    d3dpp.BackBufferFormat=ddm.Format;
    d3dpp.BackBufferHeight=nDisplayHeight=gScreenRect.bottom =ddm.Height;
    d3dpp.BackBufferWidth=nDisplayWidth=gScreenRect.right =ddm.Width;
    d3dpp.MultiSampleType=D3DMULTISAMPLE_NONE;
//  d3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD;
    d3dpp.SwapEffect=D3DSWAPEFFECT_COPY;
    d3dpp.hDeviceWindow=hWnd;
    d3dpp.PresentationInterval=D3DPRESENT_INTERVAL_DEFAULT;
    d3dpp.FullScreen_RefreshRateInHz=D3DPRESENT_RATE_DEFAULT;

    if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING ,&d3dpp,&g_pd3dDevice)))
    {
        ErrorMessage("Unable to Create Device");
        return E_FAIL;
    }

    if(FAILED(g_pd3dDevice->CreateOffscreenPlainSurface(ddm.Width, ddm.Height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &g_pSurface, NULL)))
    {
        ErrorMessage("Unable to Create Surface");
        return E_FAIL;
    }

g_pd3dDevice->GetBackBuffer(0,0,D3DBACKBUFFER_TYPE_MONO,&g_pSurface);
D3DXSaveSurfaceToFile("d:\\v\\temp.bmp",D3DXIFF_BMP,g_pSurface,NULL,NULL);

问题是,输出文件的大小为5MB,但在输出中只显示黑色。虽然在相同的代码中,如果我使用GetFrontBufferData,我可以成功捕获屏幕。我做错了吗?请帮帮我..

2 个答案:

答案 0 :(得分:1)

您无法捕获后备缓冲区的屏幕截图。

前缓冲后备缓冲关系的工作原理如下:后备缓冲区被擦除,然后一次绘制一个绘制调用的场景。一旦它准备就好,它就会被前缓冲器翻转,这样前缓冲器会在后缓冲器再次擦拭时显示最终图像。

从理论上讲,后备缓冲区有一个你想要的数据,但我不相信你能够可靠地获得这种状态。前缓冲器专为此任务而设计。

答案 1 :(得分:0)

以下是我截取屏幕截图的方式:

IDirect3DSurface9 *offscreenSurface = 0;
d3dDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &offscreenSurface);
D3DXSaveSurfaceToFile( filename, D3DXIFF_BMP, offscreenSurface, 0, 0 )

请注意,此代码在调用 Present之前运行