9da*_*dan 3 windows direct3d wic stretchdibits direct2d
我计时了一个使用多个StretchBlt和StretchDIBits调用的DDB绘图操作.
我发现,完成时间与目标窗口大小成比例地增加/减少.
使用900x600窗口需要大约5ms,但是对于1920x1080,它需要大约55ms(源图像是1280x640).
看来Stretch .. API不使用任何硬件加速功能.
创建源图像(实际上这是临时绘图画布)CreateDIBSection因为我需要为绘制的每个帧生成(拉伸和合并)位图的像素数据.
让我们假设,Windows GDI是没有希望的.那么有希望的替代方案是什么?
我考虑使用WIC方法的D3D,D2D(写入WIC位图并使用D2D绘制它然后从WIC位图读回像素数据).
我计划用WIC方法尝试D2D,因为我需要很快使用大量的文本绘图功能.
但似乎WIC并不那么有希望:WIC位图处理最有效的像素格式是什么?
我今天已经实施了D2D + WIC例程.测试结果非常好.
使用我之前的GDI StretchDIBits版本,将1280x640 DDB绘制到1920x1080窗口需要20~60ms的时间.切换到Direct2D + WIC后,通常需要不到5ms,图像质量看起来也会更好.
我使用ID2D1HwndRenderTarget和WicBitmapRenderTarget,因为我需要读/写原始像素数据.
HWndRenderTarget仅用于屏幕绘制(WM_PAINT).
HWndRenderTarget的主要优点是目标窗口大小不会影响绘图性能.
WicBitmapRenderTarget用作临时绘图画布(作为GDI绘图中的Memory DC).我们可以使用WIC位图对象(如GDI DIBSection)创建WicBitmapRenderTarget.我们可以随时从/向此WIC位图读/写原始像素数据.它也非常快.对于旁注,有点类似的D3D GetFrontBufferData调用真的很慢.
实际像素I/O通过IWICBitmap和IWICBitmapLock接口完成.
写作:
IWICBitmapPtr m_wicRemote;
...
const uint8* image = ...;
...
WICRect rcLock = { 0, 0, width, height };
IWICBitmapLockPtr wicLock;
hr = m_wicRemote->Lock(&rcLock, WICBitmapLockWrite, &wicLock);
if (SUCCEEDED(hr))
{
UINT cbBufferSize = 0;
BYTE *pv = NULL;
hr = wicLock->GetDataPointer(&cbBufferSize, &pv);
if (SUCCEEDED(hr))
{
memcpy(pv, image, cbBufferSize);
}
}
m_wicRenderTarget->BeginDraw();
m_wicRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
ID2D1BitmapPtr d2dBitmap;
hr = m_wicRenderTarget->CreateBitmapFromWicBitmap(m_wicRemote, &d2dBitmap.GetInterfacePtr());
if (SUCCEEDED(hr))
{
float cw = (renderTargetSize.width / 2);
float ch = renderTargetSize.height;
float x, y, w, h;
FitFrameToCenter(cw, ch, (float)width, (float)height, x, y, w, h);
m_wicRenderTarget->DrawBitmap(d2dBitmap, D2D1::RectF(x, y, x + w, y + h));
}
m_wicRenderTarget->EndDraw();
Run Code Online (Sandbox Code Playgroud)
读:
IWICBitmapPtr m_wicCanvas;
IWICBitmapLockPtr m_wicLockedData;
...
UINT width, height;
HRESULT hr = m_wicCanvas->GetSize(&width, &height);
if (SUCCEEDED(hr))
{
WICRect rcLock = { 0, 0, width, height };
hr = m_wicCanvas->Lock(&rcLock, WICBitmapLockRead, &m_wicLockedData);
if (SUCCEEDED(hr))
{
UINT cbBufferSize = 0;
BYTE *pv = NULL;
hr = m_wicLockedData->GetDataPointer(&cbBufferSize, &pv);
if (SUCCEEDED(hr))
{
return pv; // return data pointer
// need to Release m_wicLockedData after reading is done
}
}
}
Run Code Online (Sandbox Code Playgroud)
画画:
ID2D1HwndRenderTargetPtr m_renderTarget;
....
D2D1_SIZE_F renderTargetSize = m_renderTarget->GetSize();
m_renderTarget->BeginDraw();
m_renderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
m_renderTarget->Clear(D2D1::ColorF(D2D1::ColorF::Black));
ID2D1BitmapPtr d2dBitmap;
hr = m_renderTarget->CreateBitmapFromWicBitmap(m_wicCanvas, &d2dBitmap.GetInterfacePtr());
if (SUCCEEDED(hr))
{
UINT width, height;
hr = m_wicCanvas->GetSize(&width, &height);
if (SUCCEEDED(hr))
{
float x, y, w, h;
FitFrameToCenter(renderTargetSize.width, renderTargetSize.height, (float)width, (float)height, x, y, w, h);
m_renderTarget->DrawBitmap(d2dBitmap, D2D1::RectF(x, y, x + w, y + h));
}
}
m_renderTarget->EndDraw();
Run Code Online (Sandbox Code Playgroud)
在我看来,GDI Stretch..API在Windows 7+设置中完全没用(对于性能敏感的应用程序).
另请注意,与Direct3D不同,Direct2D中的基本图形操作(如文本绘制,绘图绘制)非常简单.
| 归档时间: |
|
| 查看次数: |
1500 次 |
| 最近记录: |