首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何直接访问显卡的输出?

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

Stack Overflow用户
提问于 2016-07-22 21:57:37
回答 1查看 6.3K关注 0票数 10

显卡通常会把它们的输出写到我可以访问的内存中的某个地方吗?我一定要用司机吗?如果是的话,我可以使用OpenGL吗?

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

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

是否可以执行选项1,只读取内存中的输出?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-07-24 07:00:45

我不使用Linux编写代码,但在Windows中(您无论如何都是在模拟器中运行它),您可以使用WinAPI直接从3派对应用程序访问任何窗口甚至桌面的画布。有些GPU覆盖可能很难捕捉(特别是基于DirectX的),但目前为止,我的GL/GLSL没有问题。

如果您可以访问App,您可以直接使用glReadPixelsGL中提取图像(但这只适用于当前基于GL的呈现)。

  1. 使用glReadPixels如前所述,这必须在目标应用程序中直接实现,因此您需要有源代码或在正确的地点/时间注入代码。我用来截取这段代码: 虚空OpenGLscreen::屏幕截图(图形:TBitmap *bmp) { if (bmp==NULL)返回;int *dat=new intxs*ys,x,y,a,*p;if (dat==NULL)返回;bmp->HandleType=bmDIB;bmp->PixelFormat=pf32bit;if (bmp->宽度!=xs!=(bmp->高度!=ys) bmp->SetSize(xs,ys);如果(bmp->宽度=xs)&(bmp->高度=ys){ glReadPixels(0,0,xs,ys,GL_BGRA,GL_UNSIGNED_BYTE,dat);glFinish();for (a=0,y=ys-1;y>=0;y-) (p=(int*)bmp->ScanLiney,x=0;x在xs,ys是OpenGL窗口分辨率的地方,您可以忽略整个bmp内容(这是用于存储屏幕快照的VCL位图),也可以忽略for --它只是将图像从缓冲区复制到位图。所以重要的事情就是: int *dat=new intxs*ys;//每个像素为32位int glReadPixels(0,0,xs,ys,GL_BGRA,GL_UNSIGNED_BYTE,dat);glFinish(); 您需要在呈现完成后执行此代码,否则将获得未完成的或空的缓冲区。我在重绘/重绘事件之后使用它。如前所述,这将只获得GL呈现的内容,所以如果您的应用程序结合了GDI+OpenGL,那么最好使用下一种方法。
  2. WinAPI approach 为了获得任何窗口的画布图像,我编写了以下类: //--------------------------------------------------------------------------- //-屏幕截图: 1.00恩达;TCanvas *scr;图形:TBitmap *bmp;int x0,y0,xs,ys;scrcap() { hnd=NULL;hnda=NULL;scr=new TCanvas();bmp=new图形:TBitmap;#ifdef _mmap_h mmap_new('scrc',scr,sizeof(TCanvas();mmap_new('scrc',bmp,sizeof(TCanvas();mmap_new(‘scrc’,bmp,sizeof(图形::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)删除scr;scr=NULL;if (bmp)删除bmp;bmp=NULL;} void (HWND _hnd=NULL) { RECT r;if (scr==NULL)返回;if (bmp==NULL)返回;bmp->SetSize(1,1);if (!IsWindow(_hnd)) _hnd=hnd;scr->HWND=GetDC(_hnd);hnda=_hnd;resize();} void (){ if (!IsWindow(hnda))返回;RECT r;// GetWindowRect(hnda,&r);GetClientRect(hnda,&r);x0=r.left;xs=r.right-x0;y0=r.top;ys=r.底部-Y0;bmp->SetSize(xs,ys);xs=bmp->宽度;ys=bmp->高度;}{ if (scr==NULL)返回;if (bmp==NULL)返回;bmp->画布->CopyRect(Rect(0,0,xs,ys),scr,TRect(x0,y0,x0+xs,y0+ys));};//--------------------------------------------------------------------------- //-//------------------------- 同样,它使用VCL,因此可以将位图、bmp和画布scr重写为您的编程环境样式。此外,它还包含了一些_mmap_h代码块,它们只用于调试/跟踪内存指针,这些指针与我当时所面临的一些讨厌的编译器错误有关,我编写了以下文章。 用法很简单: // globals scrcap;// init cap.init();// on屏幕截图cap.capture();//此处使用cap.bmp 如果您调用cap.init(),它将锁定整个windows桌面。如果您调用cap.init(window_handle),它将锁定特定的可视窗口/组件。若要从第3应用程序端获取窗口句柄,请参见:
代码语言:javascript
运行
复制
- [is ther a way an app can display a message without the use of messagebox API?](https://reverseengineering.stackexchange.com/a/11920/4709)

对不起,它是在SE/RE上,而不是在SE/SO上,但是我在这里回答这个话题的内容被删除了。我用这个拍摄视频..。我的答案中的所有动画GIF都是由这个代码创建的。在我这个答案的底部还可以看到另一个例子:

代码语言:javascript
运行
复制
- [Image to ASCII art conversion](https://stackoverflow.com/a/32987834/2521214)

正如您所看到的,它也适用于媒体播放器经典的DirectX覆盖(即使是PrintScreen函数也不能正确地实现)。正如我所写的,我对此还没有任何问题。

必须从应用程序主线程(WNDPROC)调用Beware可视内容 WinAPI 调用,否则可能会发生严重问题,导致应用程序中任意位置的随机无关WinAPI调用异常。

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38535809

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档