2014-11-29 16 views
1

DXGI Desktop Duplication에 대해 알고 싶습니다. 많이 읽었으며 Microsoft 웹 사이트의 DesktopDuplication 샘플 일부에서 복사 한 코드입니다. 내 계획은 다른 프로그램을 위해 새로운 텍스처를 만들고 싶기 때문에 DesktopImage에서 버퍼 또는 배열을 가져 오는 것입니다. 누군가가 내가 할 수있는 것을 설명 할 수 있기를 바랍니다. 내가 제대로 이해 해요 경우DXGI DirectX 11 Desktop Duplication에 대한 버퍼 또는 어레이 이해에 대한 이해

void DesktopDublication::GetFrame(_Out_ FRAME_DATA* Data, _Out_ bool* Timeout) 
{ 
    IDXGIResource* DesktopResource = nullptr; 
    DXGI_OUTDUPL_FRAME_INFO FrameInfo; 

    // Get new frame 
    HRESULT hr = m_DeskDupl->AcquireNextFrame(500, &FrameInfo, &DesktopResource); 
    if (hr == DXGI_ERROR_WAIT_TIMEOUT) 
    { 
     *Timeout = true; 

    } 
    *Timeout = false; 

    if (FAILED(hr)) 
    { 

    } 

    // If still holding old frame, destroy it 
    if (m_AcquiredDesktopImage) 
    { 
     m_AcquiredDesktopImage->Release(); 
     m_AcquiredDesktopImage = nullptr; 
    } 

    // QI for IDXGIResource 
    hr = DesktopResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void **>(&m_AcquiredDesktopImage)); 
    DesktopResource->Release(); 
    DesktopResource = nullptr; 
    if (FAILED(hr)) 
    { 

    } 

    // Get metadata 
    if (FrameInfo.TotalMetadataBufferSize) 
    { 
     // Old buffer too small 
     if (FrameInfo.TotalMetadataBufferSize > m_MetaDataSize) 
     { 
      if (m_MetaDataBuffer) 
      { 
       delete[] m_MetaDataBuffer; 
       m_MetaDataBuffer = nullptr; 
      } 
      m_MetaDataBuffer = new (std::nothrow) BYTE[FrameInfo.TotalMetadataBufferSize]; 
      if (!m_MetaDataBuffer) 
      { 
       m_MetaDataSize = 0; 
       Data->MoveCount = 0; 
       Data->DirtyCount = 0; 

      } 
      m_MetaDataSize = FrameInfo.TotalMetadataBufferSize; 
     } 

     UINT BufSize = FrameInfo.TotalMetadataBufferSize; 

     // Get move rectangles 
     hr = m_DeskDupl->GetFrameMoveRects(BufSize, reinterpret_cast<DXGI_OUTDUPL_MOVE_RECT*>(m_MetaDataBuffer), &BufSize); 
     if (FAILED(hr)) 
     { 
      Data->MoveCount = 0; 
      Data->DirtyCount = 0; 

     } 
     Data->MoveCount = BufSize/sizeof(DXGI_OUTDUPL_MOVE_RECT); 

     BYTE* DirtyRects = m_MetaDataBuffer + BufSize; 
     BufSize = FrameInfo.TotalMetadataBufferSize - BufSize; 

     // Get dirty rectangles 
     hr = m_DeskDupl->GetFrameDirtyRects(BufSize, reinterpret_cast<RECT*>(DirtyRects), &BufSize); 
     if (FAILED(hr)) 
     { 
      Data->MoveCount = 0; 
      Data->DirtyCount = 0; 

     } 
     Data->DirtyCount = BufSize/sizeof(RECT); 

     Data->MetaData = m_MetaDataBuffer; 
    } 

    Data->Frame = m_AcquiredDesktopImage; 
    Data->FrameInfo = FrameInfo; 
} 

답변

2

, 당신은 현재의 바탕 화면 이미지를 얻을 개인 텍스처로 복제 한 다음 창에 그 개인 텍스처를 렌더링합니다. 먼저 Direct3D 11을 읽고 DXGI에서 얻은 텍스처 오브젝트를 사용하여 D3D를 사용하여 장면을 렌더링하는 방법을 배웁니다. This, thisthis으로 D3D11을 시작할 수 있습니다. 또한 코드를 복사 한 샘플 소스를 읽는 데 약간의 시간을 할애 할 것입니다. Here은 해당 샘플의 전체 소스 코드에 대한 링크입니다.

실제로 텍스처 데이터를 얻을 그것을 밖으로 렌더링하려면 다음을 수행해야합니다

1). D3D11 장치 개체 및 장치 컨텍스트를 만듭니다.

2). 그래픽 카드의 Vertex 및 Pixel 셰이더를 작성하고 컴파일 한 다음 응용 프로그램에로드하십시오.

3). 입력 레이아웃 개체를 만들고 장치에 설정하십시오.

4). 장치에 대해 필요한 블렌드, 심도 스텐실 및 래스터 라이저 상태를 초기화합니다.

5). Texture 객체와 Shader Resource View 객체를 만듭니다.

6). 위의 코드를 사용하여 Desktop Duplication 텍스처를 가져옵니다.

7). CopyResource을 사용하여 텍스처에 데이터를 복사하십시오.

8). 텍스처를 화면에 렌더링하십시오.

이것은 데스크톱 중 하나에 표시된 모든 데이터를 텍스처로 캡처합니다. 데스크탑의 지저분한 직사각형은 처리하지 않습니다. 이동 된 영역에 대한 처리는 수행하지 않습니다. 이것은 베어 본 (bare bones)의 바탕 화면을 캡처하여 다른 곳의 코드에 표시합니다.

자세한 내용은 샘플에서 기본적으로 요구하는대로 링크 된 리소스를 읽고 샘플 코드를 살펴보십시오.

+0

안녕하세요. Alex, 고맙습니다. 하지만 바탕 화면 복제본을 창이나 장면으로 렌더링하고 싶지는 않습니다. 다른 응용 프로그램에서 텍스처가 필요합니다. 바이트 배열이나 버퍼에있는 데스크탑 이미지의 데이터 또는 모든 픽셀에 대해 빨간색 녹색 파란색과 알파 만 있으면됩니다. 어떤 사람이이 일이 어떻게 이루어지는 지 말해 줄 수 있습니까? – Boke

+0

그래서 당신이 정말로 요구하는 것은 나중에 데이터를 검색 할 수 있도록 파일에 데이터를 저장하는 방법입니다. – Alex

2

내 마지막 대답에이 내용을 집어 넣은 것이 옳은 느낌을주지 못했기 때문에 나는 두 번째를 만들기로 결정했습니다.

데스크톱 데이터를 파일로 읽으려면 D3D11 장치 개체, D3D11_USAGE_STAGING 플래그가 설정된 텍스처 개체 및 바탕 화면 텍스처의 RGBA 픽셀 데이터를 사용자가 원하는 것으로 변환하는 방법이 필요합니다 필요. 기본 절차는 원래 대답에있는 간단한 버전입니다.

1). D3D11 장치 개체 및 장치 컨텍스트를 만듭니다.

2). Desktop Texture와 같은 형식으로 스테이징 텍스처를 만듭니다.

3).CopyResource을 사용하여 바탕 화면 텍스처를 스테이징 텍스처로 복사하십시오.

4). ID3D11DeviceContext::Map()을 사용하여 스테이징 텍스처에 포함 된 데이터에 대한 포인터를 가져옵니다.

Map의 작동 방식을 알고 있는지, 단일 이진 스트림에서 이미지 파일을 쓸 수 있는지 확인하십시오. 이미지 버퍼에 패딩이있을 수도 있으므로 필터링해야 할 수도 있습니다. 또한 free을 호출하는 대신 Unmap 버퍼를 확인하십시오. 버퍼가 거의 확실하게 CRT에 속하지 않으므로 사용자에게 제공됩니다.

+0

안녕하세요, Alex 님, 어제 시도해 보았습니다. 메모리의 주소가 있지만 비어 있었으므로 오늘 새 코드를 게시합니다. 고마워요! – Boke