DXGI BY Freebasic

Windows specific questions.
xiaoyao
Posts: 96
Joined: May 05, 2020 2:01

DXGI BY Freebasic

Postby xiaoyao » Jun 18, 2021 21:12

how to change this to freebasic?

DxgiGrab.h

Code: Select all

#pragma once

#ifdef _USRDLL
#define API_DECLSPEC  __declspec(dllexport)
#else
#define API_DECLSPEC  __declspec(dllimport)
#endif

#ifdef __cplusplus
extern "C" {
#endif
   API_DECLSPEC void   * dxgi_create(void);
   API_DECLSPEC void     dxgi_destroy(void *);
   API_DECLSPEC int     dxgi_get_size(void *);
   API_DECLSPEC int     dxgi_get_width(void *);
   API_DECLSPEC int     dxgi_get_height(void *);
   API_DECLSPEC bool     dxgi_get_frame(void *, char *);
#ifdef __cplusplus
}
#endif

DxgiGrab.cpp

Code: Select all

/*
   作者:windpiaoxue
   联系方式:2977493715
*/

#include "DxgiGrab.h"
#include <d3d11.h>
#include <dxgi1_2.h>

#pragma comment(lib, "D3D11.lib")
#pragma comment(lib, "DXGI.lib")

#define RESET_OBJECT(obj)   { if(obj) obj->Release(); obj = nullptr; }

struct DxgiInfo {
   DxgiInfo() {

   }

   ~DxgiInfo() {
      RESET_OBJECT(m_pDevice);
      RESET_OBJECT(m_pContext);
      RESET_OBJECT(m_pDeskDupl);
   }

   ID3D11Device         * m_pDevice = nullptr;
   ID3D11DeviceContext      * m_pContext = nullptr;
   IDXGIOutputDuplication   * m_pDeskDupl = nullptr;
   int                    m_nWidth = 0;
   int                    m_nHeight = 0;
};

void * dxgi_create(void) {
   DxgiInfo * pDxgiInfo = new DxgiInfo;

   HRESULT hResult = -1;

   // Driver types supported
   D3D_DRIVER_TYPE DriverTypes[] =
   {
      D3D_DRIVER_TYPE_HARDWARE,
      D3D_DRIVER_TYPE_WARP,
      D3D_DRIVER_TYPE_REFERENCE,
   };
   UINT uNumDriverTypes = ARRAYSIZE(DriverTypes);

   // Feature levels supported
   D3D_FEATURE_LEVEL FeatureLevels[] =
   {
      D3D_FEATURE_LEVEL_11_0,
      D3D_FEATURE_LEVEL_10_1,
      D3D_FEATURE_LEVEL_10_0,
      D3D_FEATURE_LEVEL_9_1
   };
   UINT uNumFeatureLevels = ARRAYSIZE(FeatureLevels);

   D3D_FEATURE_LEVEL FeatureLevel;
   //
   // Create D3D device
   //
   for (UINT DriverTypeIndex = 0; DriverTypeIndex < uNumDriverTypes; ++DriverTypeIndex) {
      hResult = D3D11CreateDevice(
         nullptr,
         DriverTypes[DriverTypeIndex],
         nullptr,
         0,
         FeatureLevels,
         uNumFeatureLevels,
         D3D11_SDK_VERSION,
         &pDxgiInfo->m_pDevice,
         &FeatureLevel,
         &pDxgiInfo->m_pContext
      );
      if (SUCCEEDED(hResult)) {
         break;
      }
   }

   if (FAILED(hResult)) {
      delete pDxgiInfo;
      return nullptr;
   }


   //
   // Get DXGI device
   //
   IDXGIDevice * pDxgiDevice = nullptr;
   hResult = pDxgiInfo->m_pDevice->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&pDxgiDevice));
   if (FAILED(hResult)) {
      delete pDxgiInfo;
      return nullptr;
   }

   //
   // Get DXGI adapter
   //
   IDXGIAdapter * pDxgiAdapter = nullptr;
   hResult = pDxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&pDxgiAdapter));
   RESET_OBJECT(pDxgiDevice);
   if (FAILED(hResult)) {
      delete pDxgiInfo;
      return nullptr;
   }

   //
   // Get output
   //
   INT nOutput = 0;
   IDXGIOutput * pDxgiOutput = nullptr;
   hResult = pDxgiAdapter->EnumOutputs(nOutput, &pDxgiOutput);
   RESET_OBJECT(pDxgiAdapter);
   if (FAILED(hResult)) {
      delete pDxgiInfo;
      return nullptr;
   }

   //
   // QI for Output 1
   //
   IDXGIOutput1 * pDxgiOutput1 = nullptr;
   hResult = pDxgiOutput->QueryInterface(__uuidof(pDxgiOutput1), reinterpret_cast<void**>(&pDxgiOutput1));
   RESET_OBJECT(pDxgiOutput);
   if (FAILED(hResult)) {
      delete pDxgiInfo;
      return nullptr;
   }

   //
   // Create desktop duplication
   //
   hResult = pDxgiOutput1->DuplicateOutput(pDxgiInfo->m_pDevice, &pDxgiInfo->m_pDeskDupl);
   RESET_OBJECT(pDxgiOutput1);

   if (FAILED(hResult)) {
      delete pDxgiInfo;
      return nullptr;
   }

   DXGI_OUTDUPL_DESC dxgiOutDesc;
   pDxgiInfo->m_pDeskDupl->GetDesc(&dxgiOutDesc);
   pDxgiInfo->m_nWidth = dxgiOutDesc.ModeDesc.Width;
   pDxgiInfo->m_nHeight = dxgiOutDesc.ModeDesc.Height;
   return pDxgiInfo;
}

void dxgi_destroy(void * pDxgi) {
   DxgiInfo * pDxgiInfo = reinterpret_cast<DxgiInfo *>(pDxgi);

   delete pDxgiInfo;
}

int dxgi_get_size(void * pDxgi) {
   DxgiInfo * pDxgiInfo = reinterpret_cast<DxgiInfo *>(pDxgi);
   return pDxgiInfo->m_nWidth * pDxgiInfo->m_nHeight * 4;
}

int dxgi_get_width(void * pDxgi) {
   DxgiInfo * pDxgiInfo = reinterpret_cast<DxgiInfo *>(pDxgi);
   return pDxgiInfo->m_nWidth;
}

int dxgi_get_height(void * pDxgi) {
   DxgiInfo * pDxgiInfo = reinterpret_cast<DxgiInfo *>(pDxgi);
   return pDxgiInfo->m_nHeight;
}

bool dxgi_get_frame(void * pDxgi, char * pOut) {
   DxgiInfo * pDxgiInfo = reinterpret_cast<DxgiInfo *>(pDxgi);

   IDXGIResource * pDesktopResource = nullptr;
   DXGI_OUTDUPL_FRAME_INFO FrameInfo;

   pDxgiInfo->m_pDeskDupl->ReleaseFrame();
   HRESULT hResult = pDxgiInfo->m_pDeskDupl->AcquireNextFrame(0, &FrameInfo, &pDesktopResource);

   if (FAILED(hResult)) {
      return false;
   }

   //
   // query next frame staging buffer
   //
   ID3D11Texture2D * pAcquiredDesktopImage = nullptr;
   hResult = pDesktopResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void **>(&pAcquiredDesktopImage));
   RESET_OBJECT(pDesktopResource);

   if (FAILED(hResult)) {
      return false;
   }

   //
   // copy old description
   //
   D3D11_TEXTURE2D_DESC frameDescriptor;
   pAcquiredDesktopImage->GetDesc(&frameDescriptor);

   //
   // create a new staging buffer for fill frame image
   //
   ID3D11Texture2D *hNewDesktopImage = nullptr;
   frameDescriptor.Usage = D3D11_USAGE_STAGING;
   frameDescriptor.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
   frameDescriptor.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
   frameDescriptor.BindFlags = 0;
   frameDescriptor.MiscFlags = 0;
   frameDescriptor.MipLevels = 1;
   frameDescriptor.ArraySize = 1;
   frameDescriptor.SampleDesc.Count = 1;
   hResult = pDxgiInfo->m_pDevice->CreateTexture2D(&frameDescriptor, nullptr, &hNewDesktopImage);

   if (FAILED(hResult)) {
      return false;
   }

   //
   // copy next staging buffer to new staging buffer
   //
   pDxgiInfo->m_pContext->CopyResource(hNewDesktopImage, pAcquiredDesktopImage);

   D3D11_MAPPED_SUBRESOURCE dsec = { 0 };
   hResult = pDxgiInfo->m_pContext->Map(hNewDesktopImage, 0, D3D11_MAP_READ, 0, &dsec);
   if (SUCCEEDED(hResult)) {
      if (dsec.pData != nullptr) {
         for (int y = 0; y < pDxgiInfo->m_nHeight; ++y) {
            memcpy(pOut + y * pDxgiInfo->m_nWidth * 4, (char*)dsec.pData + y * dsec.RowPitch, pDxgiInfo->m_nWidth * 4);
         }
      }
      pDxgiInfo->m_pContext->Unmap(hNewDesktopImage, 0);
   }

   RESET_OBJECT(hNewDesktopImage);
   RESET_OBJECT(pAcquiredDesktopImage);

   return dsec.pData != nullptr;
}
D.J.Peters
Posts: 8301
Joined: May 28, 2005 3:28
Contact:

Re: DXGI BY Freebasic

Postby D.J.Peters » Jun 19, 2021 0:11

FreeBASIC comes with D3D9 include files but not D3D11 !

You should ask in the Windows forum section not here
Or a forum mod can move this post in the right section.

Joshy
Imortis
Moderator
Posts: 1777
Joined: Jun 02, 2005 15:10
Location: USA
Contact:

Re: DXGI BY Freebasic

Postby Imortis » Jun 19, 2021 3:03

Moved.
adeyblue
Posts: 78
Joined: Nov 07, 2019 20:08

Re: DXGI BY Freebasic

Postby adeyblue » Jun 20, 2021 0:59

I would say: while not this method, there's probably hundreds of versions of GDI screenshot code on this forum, but it doesn't look like anyone's ever done it. Until now

Code: Select all

#include once "windows.bi"
#include once "win/windowsx.bi"

Function GetScreenshot(ByRef bitmapInfo As BITMAPINFOHEADER) As Any Ptr

    dim hdc As HDC = GetDC(0)
    dim sWidth As Long = GetDeviceCaps(hdc, HORZRES)
    dim sHeight As Long = GetDeviceCaps(hdc, VERTRES)
    dim hdcCompat As HDC = CreateCompatibleDC(hdc)
    dim areaBytes As Long = (sWidth  * 4) * sHeight
    dim bmInfo As BITMAPINFO
    bmInfo.bmiHeader.biSize = SizeOf(bmInfo.bmiHeader)
    bmInfo.bmiHeader.biWidth = sWidth
    bmInfo.bmiHeader.biPlanes = 1
    bmInfo.bmiHeader.biHeight = sHeight
    bmInfo.bmiHeader.biBitCount = 32
    bmInfo.bmiHeader.biSizeImage = areaBytes
    bmInfo.bmiHeader.biCompression = BI_RGB
    dim hbm As HBITMAP = CreateDIBitmap(hdc, @bmInfo.bmiHeader, 0, 0, 0, DIB_RGB_COLORS)
    dim hBmOld As HBITMAP = SelectBitmap(hdcCompat, hbm)
    BitBlt(hdcCompat, 0, 0, sWidth, sHeight, hdc, 0, 0, SRCCOPY)
    ReleaseDC(0, hdc)
    SelectBitmap(hdcCompat, hbmOld)
    dim pBmBits As Any Ptr = CAllocate(areaBytes)
    GetBitmapBits(hbm, areaBytes, pBmBits)
    DeleteBitmap(hbm)
    DeleteDC(hdcCompat)
    bitmapInfo = bmInfo.bmiHeader
    Return pBmBits

End Function

Sub DrawToScreen(ByVal pBits As Any Ptr, ByRef bmInfoHeader As BITMAPINFOHEADER)

    dim hdc As HDC = GetDC(0)
    dim sWidth As Long = bmInfoHeader.biWidth
    dim sHeight As Long = Abs(bmInfoHeader.biHeight)
    dim hdcCompat As HDC = CreateCompatibleDC(hdc)
    dim bmInfo As BITMAPINFO
    bmInfo.bmiHeader = bmInfoHeader
    bmInfo.bmiHeader.biHeight = -bmInfo.bmiHeader.biHeight '' so it draws the right way around instead of upside down
    dim hbm As HBITMAP = CreateDIBitmap(hdc, @bmInfoHeader, CBM_INIT, pBits, @bmInfo, DIB_RGB_COLORS)
    dim hbmOld As HBITMAP = SelectBitmap(hdcCompat, hbm)
    BitBlt(hdc, 100, 100, sWidth, sHeight, hdcCompat, 0, 0, SRCCOPY)
    SelectBitmap(hdcCompat, hbmOld)
    DeleteDC(hdcCompat)
    DeleteBitmap(hbm)
    ReleaseDC(0, hdc)

End Sub

dim bmInfo As BITMAPINFOHEADER
dim pBits As Any Ptr = GetScreenshot(bmInfo)
'' do whatever with the raw pixels
'' copy them back to the screen as an example
DrawToScreen(pBits, bmInfo)
DeAllocate(pBits)

If you run this code as-is, you'll need to cause a redraw of the screen to get rid of all of the copied image

Return to “Windows”

Who is online

Users browsing this forum: No registered users and 3 guests