绘制缓冲区到 D3D9 纹理

Drawing buffer to D3D9 texture

我正在尝试将 CEF 缓冲区(在 OnPaint 上返回)绘制为游戏的 D3D9 纹理,并且游戏随机预永久冻结。我想通了下面提供的代码是游戏冻结的原因,但仍然无法理解。我错过了什么?

// 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();
    }

需要说明的是:CEF 按预期渲染,没有错误,这里只是纹理渲染问题。希望得到任何帮助

经过评论讨论,我对代码做了一些修改:

// 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();

}

如上所述,绘制事件(和覆盖方法)都被调用 on the CefBrowser UI thread,并且在同一纹理被释放之前多次锁定它会导致整个 D3D 上下文死锁。

修复是将绘制事件处理程序(负责将渲染的 Chrome 图像保存到内部缓冲区)与 D3D 渲染线程(负责将内部缓冲区上传到 D3D纹理和渲染)。