你不需要做任何事情为低电平,内核或设备驱动程序来做到这一点。
您可以使用XTest X11 extension以编程方式假冒输入事件,例如(来自this posting,有another example for keyboard)。
#include <X11/extensions/XTest.h>
#include <unistd.h>
int main()
{
Display *dpy = NULL;
XEvent event;
dpy = XOpenDisplay (NULL);
/* Get the current pointer position */
XQueryPointer (dpy, RootWindow (dpy, 0),
&event.xbutton.root, &event.xbutton.window,
&event.xbutton.x_root, &event.xbutton.y_root,
&event.xbutton.x, &event.xbutton.y,
&event.xbutton.state);
/* Fake the pointer movement to new relative position */
XTestFakeMotionEvent (dpy, 0, event.xbutton.x + 100,
event.xbutton.y + 50, CurrentTime);
XSync(dpy, 0);
XCloseDisplay (dpy);
return 0;
}
要捕获的图像中的最简单的方法是使用function interposition(经由LD_PRELOAD
)为“截距”调用glXSwapBuffers
,其将被称为一次每帧的绘制过程。从那里你可以复制帧缓冲区的内容,使用glReadPixels
,并用它做你想要的。
E.g.拦截的OpenGL帧未经测试大纲:
// Function pointer to the *real* glXSwapBuffers
static void (*glx_fptr)(Display*, GLXDrawable) = NULL;
// Make sure init gets called when the shared object is loaded. GCC specific.
static void init(void) __attribute__((constructor));
static void init(void) {
dlerror();
// find the real glXSwapBuffers
glx_fptr = dlsym(RTLD_NEXT, "glXSwapBuffers");
if (NULL == glx_fptr)
fprintf(stderr, "[glvidcap] %s\n", dlerror());
}
void glXSwapBuffers(Display *dpy, GLXDrawable drawable) {
unsigned int w = 0;
unsigned int h = 0;
static int x,y;
static Window win;
static unsigned int border,depth;
// Find the window size. (You could skip this and make it all static if you
// Trust the window not to change size
XGetGeometry(dpy, drawable, &win, &x, &y, &w, &h, &border, &depth);
// Assuming frame is some memory you want the frame dumped to:
glReadPixels(0,0,w,h,GL_BGR,GL_UNSIGNED_BYTE, frame);
// Call the real function:
assert(glx_fptr);
glx_fptr(dpy, drawable);
}
然后你要编译这是一个共享对象和LD_PRELOAD
跑跑你看什么比赛前的共享对象。
如果碰巧是SDL应用程序,则可以根据需要拦截对SDL_Flip
或SDL_UpdateRect
的调用。
如果直接使用'dlopen()'加载OpenGL,您仍然可以用自己的libGL.so替换/ usr/lib中的libGL.so,尽管您的解决方案可能比此更简单。 – Flexo
你可能是对的。我不得不进入更多的C编码,我想我会继续解决我的问题。性能不算太差,令人惊讶。 – user423805