2014-10-02 2 views
3

StretchBltStretchDIBits 호출을 사용하는 DDB 드로잉 작업을 시간 초과했습니다.Windows StretchBlt API 성능

그리고 완료 시간은 대상 창 크기에 비례하여 증가/감소하는 것으로 나타났습니다.
900x600 창에서는 약 5ms가 걸리지 만 1920x1080에서는 55ms (원본 이미지는 1280x640)가 소요됩니다.

Stretch .. API는 하드웨어 가속 기능을 사용하지 않습니다.

소스 이미지 (실제로는 임시 도면 캔버스 임)는이 I 그린 프레임마다 (연신 병합 된) 비트 맵의 ​​픽셀 데이터를 생성 할 필요 CreateDIBSection때문으로 생성된다.

Windows GDI가 절망적이라고 가정 해 봅시다. 그러면 유망한 대안은 무엇입니까?

WIC 방식의 D3D, D2D (WIC 비트 맵에 쓰기 및 D2D로 그리기, WIC 비트 맵에서 픽셀 데이터 다시 읽기)를 고려했습니다.
언젠가 곧 광범위한 텍스트 그리기 기능을 사용해야 할 것이므로 WIC 방법으로 D2D를 시도 할 계획입니다.

하지만 WIC를 보인다는 약속되지 않습니다 : What is the most effective pixel format for WIC bitmap processing?

+0

예, StretchBlt가 실제로 느립니다. 또한 HALFTONE 옵션을 사용하여 더 많은 품질을 원한다면 실시간 렌더링에서 작업 할 수 없습니다. 어쨌든, 귀하의 소프트웨어는 어떤 OS를 대상으로합니까? –

+0

@AntonAngelov 대상 OS는 Windows 7 이상입니다. 현재 내 랩톱은 (GDI 기준) 900x600 @ 20fps를 원활하게 처리 할 수 ​​있으며 목표는 1920x1080 @ 30fps입니다. 다음 주에 결과가 나오면 다른 질문을하겠습니다. – 9dan

+0

좋습니다. 하지만 질문을보다 정확하게 (예 : 한 문장으로) 작성할 수 있습니까? –

답변

5

내가 구현 한 D2D + 루틴 WIC 오늘. 테스트 결과는 정말 좋습니다.

이전 GDI StretchDIBits 버전에서는 1280x640 DDB를 1920x1080 창으로 그리는 데 20 ~ 60ms의 시간이 걸렸습니다. Direct2D + WIC로 전환 한 후 일반적으로 5ms 미만으로 소요되며 화질도 좋아집니다.

원시 픽셀 데이터를 읽고 쓰려면 WicBitmapRenderTarget과 함께 ID2D1HwndRenderTarget을 사용했습니다.

HWndRenderTarget은 화면 그림 (WM_PAINT)에만 사용됩니다.
HWndRenderTarget의 주된 장점은 대상 창 크기가 그리기 성능에 영향을 미치지 않는다는 것입니다.

WicBitmapRenderTarget은 임시 드로잉 캔버스 (GDI 드로잉의 메모리 DC)로 사용됩니다. WIC 비트 맵 객체 (예 : GDI DIBSection)를 사용하여 WicBitmapRenderTarget을 만들 수 있습니다. 언제든지이 WIC 비트 맵에서 /로 원시 픽셀 데이터를 읽고 쓸 수 있습니다. 또한 매우 빠릅니다. 참고로, 약간 비슷한 D3D GetFrontBufferData 전화는 정말 느립니다.

실제 픽셀 입출력은 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(); 

읽기 :

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 Stretch.. API에 민감한 성능 (윈도우 7 + 설정에서 완전히 쓸모 응용 프로그램).

또한 Direct3D와는 달리 Direct2D에서는 텍스트 그리기, 링 그리기와 같은 기본적인 그래픽 작업이 매우 간단합니다.

+0

WIC 렌더링 대상을 사용해야하는 이유를 아직도 이해할 수 없습니다. 크기 조정 후 CPU 픽셀 조작을해야합니까? 그런데 DirectShow, Media Foundation과 같은 멀티미디어 프레임 워크를 사용해 보셨습니까? –

+0

성능 향상은 D2D 렌더링에서만 발생한다고 생각합니다. WIC는 성능 향상이 아닌 GDI DIB 섹션 API의 대체품 일뿐입니다. 스크린 레코딩을 위해 최종 픽셀 데이터가 필요하기 때문에 WIC를 사용했습니다. DirectShow는 복잡한 '핀'인터페이스 코딩과 자체 타이밍 규칙을 필요로합니다. MF에 대해 많이 알지 못합니다. – 9dan

+1

나는 본다. 이게 너에게 어울리 니깐. :) –