gpt4 book ai didi

c - 如何直接访问显卡的输出?

转载 作者:行者123 更新时间:2023-12-04 12:10:12 26 4
gpt4 key购买 nike

显卡通常会将其输出写入内存中我可以访问的某个位置吗?我必须使用驱动程序吗?如果是这样,我可以使用 OpenGL 吗?

我想知道是否可以在 Linux 上“捕获”可以直接访问 GPU 并运行 Windows 的 VM 的输出。理想情况下,我可以直接从内存访问输出,而无需接触 GPU,因为此代码将能够在 Linux 主机上运行。

另一种选择可能是编写一个 Windows 驱动程序,该驱动程序读取 GPU 的输出并将其写入内存中的某个位置。然后,在 Linux 端,一个程序可以读取这个内存。这似乎有点不可能,因为我不确定如何让主机上的进程与 guest 上的进程共享内存。

是否可以执行选项 1 并简单地从内存中读取输出?

最佳答案

我不在 下编码Linux 但在 window (无论如何你都在模拟器中运行它)你可以使用 WinAPI 直接访问任何窗口甚至桌面的 Canvas 第三名派对应用程序。一些 显卡 覆盖可能难以捕捉(尤其是基于 DirectX ),但我的 没有问题总帐/总帐单 目前。

如果您可以访问 App 源,您可以使用 glReadPixels用于从 中提取图像总帐 直接(但仅适用于当前的 GL 基于渲染)。

  • 使用 glReadPixels

    如前所述,这必须直接在目标应用程序中实现,因此您需要拥有它的源代码或在正确的位置/时间注入(inject)您的代码。我用于截取这段代码:
    void OpenGLscreen::screenshot(Graphics::TBitmap *bmp)
    {
    if (bmp==NULL) return;
    int *dat=new int[xs*ys],x,y,a,*p;
    if (dat==NULL) return;
    bmp->HandleType=bmDIB;
    bmp->PixelFormat=pf32bit;
    if ((bmp->Width!=xs)||(bmp->Height!=ys)) bmp->SetSize(xs,ys);
    if ((bmp->Width==xs)&&(bmp->Height==ys))
    {
    glReadPixels(0,0,xs,ys,GL_BGRA,GL_UNSIGNED_BYTE,dat);
    glFinish();
    for (a=0,y=ys-1;y>=0;y--)
    for (p=(int*)bmp->ScanLine[y],x=0;x<xs;x++,a++)
    p[x]=dat[a];
    }
    delete[] dat;
    }

    在哪里 xs,ys是OpenGL窗口分辨率,可以忽略整个bmp东西(它是我用来存储屏幕截图的 VCL 位图),也可以忽略 for它只是将图像从缓冲区复制到位图。所以重要的事情就是这样:
    int *dat=new int[xs*ys]; // each pixel is 32bit int
    glReadPixels(0,0,xs,ys,GL_BGRA,GL_UNSIGNED_BYTE,dat);
    glFinish();

    您需要在渲染完成后执行此代码,否则您将获得未完成或空缓冲区。我在重绘/重绘事件后使用它。如前所述,这将仅获得 GL 渲染的内容,因此如果您的应用程序结合了 GDI+OpenGL,最好使用下一种方法。
  • WinAPI方法

    为了获得任何窗口的 Canvas 图像,我编写了这个类:
    //---------------------------------------------------------------------------
    //--- screen capture ver: 1.00 ----------------------------------------------
    //---------------------------------------------------------------------------
    class scrcap
    {
    public:
    HWND hnd,hnda;
    TCanvas *scr;
    Graphics::TBitmap *bmp;
    int x0,y0,xs,ys;
    scrcap()
    {
    hnd=NULL;
    hnda=NULL;
    scr=new TCanvas();
    bmp=new Graphics::TBitmap;
    #ifdef _mmap_h
    mmap_new('scrc',scr,sizeof(TCanvas() ));
    mmap_new('scrc',bmp,sizeof(Graphics::TBitmap));
    #endif
    if (bmp)
    {
    bmp->HandleType=bmDIB;
    bmp->PixelFormat=pf32bit;
    }
    x0=0; y0=0; xs=1; ys=1;
    hnd=GetDesktopWindow();
    }
    ~scrcap()
    {
    #ifdef _mmap_h
    mmap_del('scrc',scr);
    mmap_del('scrc',bmp);
    #endif
    if (scr) delete scr; scr=NULL;
    if (bmp) delete bmp; bmp=NULL;
    }
    void init(HWND _hnd=NULL)
    {
    RECT r;
    if (scr==NULL) return;
    if (bmp==NULL) return;
    bmp->SetSize(1,1);
    if (!IsWindow(_hnd)) _hnd=hnd;
    scr->Handle=GetDC(_hnd);
    hnda=_hnd;
    resize();
    }
    void resize()
    {
    if (!IsWindow(hnda)) return;
    RECT r;
    // GetWindowRect(hnda,&r);
    GetClientRect(hnda,&r);
    x0=r.left; xs=r.right-x0;
    y0=r.top; ys=r.bottom-y0;
    bmp->SetSize(xs,ys);
    xs=bmp->Width;
    ys=bmp->Height;
    }
    void capture()
    {
    if (scr==NULL) return;
    if (bmp==NULL) return;
    bmp->Canvas->CopyRect(Rect(0,0,xs,ys),scr,TRect(x0,y0,x0+xs,y0+ys));
    }
    };
    //---------------------------------------------------------------------------
    //---------------------------------------------------------------------------
    //---------------------------------------------------------------------------

    它再次使用 VCL 所以重写位图bmp和 Canvas scr适合您的编程环境风格。也忽略 _mmap_h代码块它们只是用于调试/跟踪与我当时面临的一些讨厌的编译器错误相关的内存指针我写了这个。

    用法很简单:
    // globals
    scrcap cap;
    // init
    cap.init();

    // on screenshot
    cap.capture();
    // here use cap.bmp

    如果您调用cap.init()它将锁定整个 Windows 桌面。如果您调用cap.init(window_handle)它将锁定特定的可 window 口/组件。要从第 3 个应用程序端获取窗口句柄,请参阅:
  • is ther a way an app can display a message without the use of messagebox API?

  • 抱歉,它是在 SE/RE 上而不是在 SE/SO 上,但我在此处涉及该主题的回答已被删除。我用它来捕捉视频……我的答案中的所有动画 GIF 都是由这段代码创建的。在我的这个答案的底部可以看到另一个例子:
  • Image to ASCII art conversion

  • 如您所见,它也适用于带有经典媒体播放器的 DirectX 覆盖(即使 Windows PrintScreen 功能也无法正确执行)。正如我所写的那样,我对此还没有任何问题。

    当心 视觉的东西 WinAPI 必须从应用程序主线程 (WNDPROC) 调用调用,否则可能会出现严重问题,导致应用程序中任何地方的随机无关 WinAPI 调用异常。

    关于c - 如何直接访问显卡的输出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38535809/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com