DirectX: Render to a screen buffer without using a render target

Posted by knight666 on Stack Overflow See other posts from Stack Overflow or by knight666
Published on 2010-03-22T19:54:42Z Indexed on 2010/03/23 6:13 UTC
Read the original article Hit count: 463

Hello,

I'm writing an open source 2D game engine, and I want to support as many devices and platforms as possible. I currently only have Windows Mobile though. I'm rendering using DirectX Mobile, with DirectDraw as a fallback path. However, I've run into a bit of trouble.

It seems that while the reference driver supports createRenderTarget, many many many physical devices do not. I need some way to render to the screen without using a render target, because I render sprites using textured quads, but I also need to be able to draw individual pixels.

This is how I do it right now:

// save old values

if (Error::Failed(m_D3DDevice->GetRenderTarget(&m_D3DOldTarget)))
{
    ERROR_EXPLAIN("Could not retrieve backbuffer.");
    return false;
}

// clear render surface

if (Error::Failed(m_D3DDevice->SetRenderTarget(m_D3DRenderSurface, NULL)))
{
    ERROR_EXPLAIN("Could not set render target to render texture.");
    return false;
}

if  (Error::Failed (m_D3DDevice->Clear( 
            0,
            NULL,                        // target rectangle
            D3DMCLEAR_TARGET,
            D3DMCOLOR_XRGB(0, 0, 0),     // clear color
            1.0f, 
            0
        )
    )
)
{
    ERROR_EXPLAIN("Failed to clear render texture.");
    return false;
}

D3DMLOCKED_RECT render_rect;
if (Error::Failed(m_D3DRenderSurface->LockRect(&render_rect, NULL, NULL)))
{
    ERROR_EXPLAIN("Failed to lock render surface pixels.");
}
else
{
    m_D3DBackSurf->SetBuffer((Pixel*)render_rect.pBits);
    m_D3DRenderSurface->UnlockRect();
}

// begin scene

if (Error::Failed(m_D3DDevice->BeginScene()))
{
    ERROR_EXPLAIN("Failed to start rendering.");
    return false;
}

// =====================
// example rendering
// =====================

// some other stuff, but the most important part of rendering a sprite:
device->SetTexture(0, m_Texture));
device->SetStreamSource(0, m_VertexBuffer, sizeof(Vertex));
device->DrawPrimitive(D3DMPT_TRIANGLELIST, 0, 2);

// plotting a pixel
Surface* target = (Surface*)Device::GetRenderMethod()->GetRenderTarget();
buffer = target->GetBuffer();
buffer[somepixel] = MAKECOLOR(255, 0, 0);

// end scene

if (Error::Failed(device->EndScene()))
{
    ERROR_EXPLAIN("Failed to end scene.");
    return false;
}

// clear screen

if (Error::Failed(device->SetRenderTarget(m_D3DOldTarget, NULL)))
{
    ERROR_EXPLAIN("Couldn't set render target to backbuffer.");
    return false;
}

if (Error::Failed(device->GetBackBuffer (   
        0,
        D3DMBACKBUFFER_TYPE_MONO, 
        &m_D3DBack 
        ) 
    ) 
)
{
    ERROR_EXPLAIN("Couldn't retrieve backbuffer.");
    return false;
}

RECT dest = { 
    0, 
    0, 
    Device::GetWidth(), 
    Device::GetHeight()
};

if (Error::Failed( device->StretchRect (        
            m_D3DRenderSurface, 
            NULL,
            m_D3DBack, 
            &dest, 
            D3DMTEXF_NONE 
        )
    )
)
{
    ERROR_EXPLAIN("Failed to stretch render texture to backbuffer.");
    return false;
}

if (Error::Failed(device->Present(NULL, NULL, NULL, NULL)))
{
    ERROR_EXPLAIN("Failed to present device.");
    return false;
}

I'm looking for a way to do the same thing (render sprites using hardware acceleration and plot pixels on a buffer) without using a render target.

Thanks in advance.

© Stack Overflow or respective owner

Related posts about c++

Related posts about directx