Windows StretchBlt API性能 [英] Windows StretchBlt API performance

查看:146
本文介绍了Windows StretchBlt API性能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我为DDB绘制操作定时,该操作使用多个 StretchBlt StretchDIBits 调用。

I timed a DDB drawing operation which uses multiple StretchBlt and StretchDIBits calls.

我发现,完成时间是与目标窗口大小成比例的增加/减少。

对于900x600的窗口,它需要大约5ms,但是对于1920x1080的窗口,它需要的最大55ms(源图像为1280x640)。

And I found that, time to complete is increase/decrease proportionally to the destination window size.
With 900x600 window it takes around 5ms, but with 1920x1080 it takes as large as 55ms (source image is 1280x640).

似乎是可伸缩的。API不使用任何硬件加速功能。

It seems Stretch.. APIs don't use any hardware acceleration features.

源图像(实际上这是临时绘图画布)是使用 CreateDIBSection 创建的,因为我需要生成(

Source image (actually this is temporary drawing canvas) is created with CreateDIBSection because I need resulting (stretched and merged) bitmap's pixel data for every frame drawn.

让我们假设Windows GDI是绝望的。那么有什么有前途的选择呢?

Let's assume, Windows GDI is hopeless. Then what is the promising alternative?

我考虑了采用WIC方法的D3D,D2D(写入WIC位图并用D2D绘制,然后从WIC位图中读回像素数据) 。

我计划尝试使用WIC方法进行D2D,因为不久以后我将需要使用广泛的文本绘图功能。

I considered D3D, D2D with WIC method (write to WIC bitmap and draw it with D2D then read back pixel data from the WIC bitmap).
I planed to try D2D with WIC method because I will needed to use extensive text drawing feature sometime soon.

但似乎WIC并非如此很有前途的:什么是最有效的像素格式

But it seems WIC is not that promising: What is the most effective pixel format for WIC bitmap processing?

推荐答案

我今天已经实现了D2D + WIC例程。测试结果真的很好。

I've implemented D2D + WIC routine today. Test results are really good.

在我以前的GDI StretchDIBits 版本中,将1280x640 DDB绘制到1920x1080窗口需要20到60毫秒的时间。切换到Direct2D + WIC后,通常需要5毫秒以下的时间,而且图像质量也会更好。

With my previous GDI StretchDIBits version, it took 20 ~ 60ms time for drawing 1280x640 DDB into a 1920x1080 window. After switching to Direct2D + WIC, it usually takes under 5ms, also picture quality looks better.

我将ID2D1HwndRenderTarget与WicBitmapRenderTarget结合使用,因为我需要读取/写入原始像素数据。

I used ID2D1HwndRenderTarget with WicBitmapRenderTarget, because I need to read/write raw pixel data.

HWndRenderTarget仅用于屏幕绘画(WM_PAINT)。

HWndRenderTarget的主要优点是目标窗口大小不会影响绘图性能

HWndRenderTarget is only used for screen painting (WM_PAINT).
The main advantage of HWndRenderTarget is that the destination window size doesn't affect drawing performance.

WicBitmapRenderTarget用作临时绘图画布(作为GDI绘图中的Memory DC)。我们可以使用WIC位图对象(例如GDI DIBSection)创建WicBitmapRenderTarget。我们可以随时从该WIC位图中读取/写入原始像素数据。而且速度很快。作为旁注,有点类似的D3D GetFrontBufferData 调用确实很慢。

WicBitmapRenderTarget is used as a temporary drawing canvas (as Memory DC in GDI drawing). We can create WicBitmapRenderTarget with a WIC bitmap object (like GDI DIBSection). We can read/write raw pixel data from/to this WIC bitmap at any time. Also it's very fast. For side note, somewhat similar D3D GetFrontBufferData call is really slow.

实际像素I / O通过IWICBitmap完成

Actual pixel I/O is done through IWICBitmap and IWICBitmapLock interface.

写作:

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

阅读:

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
        }
    }
}

绘图:

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

我认为,GDI 伸展。.在Windows 7+设置中(对于性能敏感的应用程序),API完全没有用。

In my opinion, GDI Stretch.. APIs are totally useless in Windows 7+ setup (for performance sensitive applications).

还请注意,与Direct3D不同,在Direct2D中基本的图形操作(如文本绘制,ling绘制)非常简单。

Also note that, unlike Direct3D, basic graphics operations such as text drawing, ling drawing are really simple in Direct2D.

这篇关于Windows StretchBlt API性能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆