简体   繁体   English

将缓冲区绘制到 D3D9 纹理

[英]Drawing buffer to D3D9 texture

I'm trying to draw CEF buffer (returned on OnPaint) to D3D9 texture of the game, and game randomly premanently freezes.我正在尝试将 CEF 缓冲区(在 OnPaint 上返回)绘制到游戏的 D3D9 纹理,并且游戏随机预先冻结。 I figured out that code provided below is the reason of the game freeze, but still can't understand.我发现下面提供的代码是游戏冻结的原因,但仍然无法理解。 What did I miss?我错过了什么?

// To create texture I use this code
LPDIRECT3DTEXTURE9 tWebPNG;
D3DXCreateTexture(device, width, height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tWebPNG);

// And the problem in that method

    void OnPaint(CefRefPtr<CefBrowser> browser, PaintElementType type, const RectList& dirtyRects, const void* buffer, int width, int height)
    {

        D3DLOCKED_RECT LockedRect;
        D3DSURFACE_DESC SurfaceDesc;
        IDirect3DSurface9* pSurface;
        tWebPNG->GetSurfaceLevel(0, &pSurface);

        pSurface->GetDesc(&SurfaceDesc);
        pSurface->LockRect(&LockedRect, nullptr, 0);
        
        auto dest = (unsigned char*)LockedRect.pBits;
        auto src = (const char*)buffer;

        for (int i = 0; i < height; ++i)
        {
            memcpy(dest, src, width * 4);
            dest += LockedRect.Pitch;
            src += width * 4;
        }


        pSurface->UnlockRect();
    }

To be clear: CEF is rendered as expected, it have no errors and here is just texture render problem.需要明确的是:CEF 按预期渲染,没有错误,这只是纹理渲染问题。 Hope to get any help希望得到任何帮助

After discussing in comments, I have modified my code a bit:在评论中讨论后,我修改了我的代码:

// Modified OnPaint to work with mutaxes
    void OnPaint(CefRefPtr<CefBrowser> browser, PaintElementType type, const RectList& dirtyRects, const void* buffer, int width, int height)
    {
        {
            std::lock_guard<std::mutex> lock(m_RenderData.dataMutex);

            // Store render data
            m_RenderData.buffer = buffer;
            m_RenderData.width = width;
            m_RenderData.height = height;
            m_RenderData.dirtyRects = dirtyRects;
            m_RenderData.changed = true;
        }

        // Wait for the main thread to handle drawing the texture
        std::unique_lock<std::mutex> lock(m_RenderData.cvMutex);
        m_RenderData.cv.wait(lock);
    }


// This method is intended to draw into d3d9 layer
void Browser::draw()
{
    std::lock_guard<std::mutex> lock(m_RenderData.dataMutex);

    IDirect3DSurface9* pSurface;

    tWebPNG->GetSurfaceLevel(0, &pSurface);

    if (m_RenderData.changed)
    {
        // Lock surface
        D3DLOCKED_RECT LockedRect;
        if (FAILED(pSurface->LockRect(&LockedRect, nullptr, 0))) {
            m_RenderData.cv.notify_all();
            return;
        }

        // Update changed state
        m_RenderData.changed = false;

        D3DSURFACE_DESC SurfaceDesc;
        IDirect3DSurface9* pSurface;
        tWebPNG->GetSurfaceLevel(0, &pSurface);

        pSurface->GetDesc(&SurfaceDesc);
        pSurface->LockRect(&LockedRect, nullptr, 0);

        auto dest = (unsigned char*)LockedRect.pBits;
        auto src = (const char*)m_RenderData.buffer;

        for (int i = 0; i < height; ++i)
        {
            memcpy(dest, src, width * 4);
            dest += LockedRect.Pitch;
            src += width * 4;
        }

        // Unlock surface
        pSurface->UnlockRect();
    }

    D3DXVECTOR3* vector = new D3DXVECTOR3(0, 0, 0);

    sprite->Begin(D3DXSPRITE_ALPHABLEND);
    sprite->Draw(tWebPNG, NULL, NULL, vector, 0xFFFFFFFF);
    sprite->End();
    
    m_RenderData.cv.notify_all();

}

As discussed above, the paint event (and override method) are both called on the CefBrowser UI thread , and locking the same texture multiple times before it gets released will deadlock your entire D3D context.如上所述,绘制事件(和覆盖方法)都在 CefBrowser UI 线程上调用,并且在释放之前多次锁定同一个纹理会使整个 D3D 上下文死锁。

The fix is to separate the paint event handler (which is responsible for saving the rendered Chrome image to an internal buffer) from the D3D render thread (which is responsible for uploading the internal buffer to the D3D texture and rendering with it).修复方法是将绘制事件处理程序(负责将渲染的 Chrome 图像保存到内部缓冲区)与 D3D 渲染线程(负责将内部缓冲区上传到 D3D 纹理并使用它进行渲染)分开。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM