Vous n'avez pas besoin de faire quoi que ce soit aussi bas niveau que les pilotes du noyau ou l'appareil pour le faire.
Vous pouvez utiliser le XTest X11 extension pour simuler des événements d'entrée par programme, par exemple (à partir de this posting, il y a 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;
}
Pour capturer les images de la façon la plus simple est d'utiliser function interposition (via LD_PRELOAD
) à « intercepter » les appels à glXSwapBuffers
, qui sera appelée une fois chaque image est tirée. De là, vous pouvez copier le contenu du framebuffer, en utilisant glReadPixels
et faire avec ce que vous voulez.
E.g. contours non testés pour intercepter des trames 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);
}
Alors, vous voulez compiler comme objet partagé et LD_PRELOAD
qui a partagé l'objet avant d'exécuter quelque jeu que vous regardez.
S'il s'agit d'une application SDL, vous pouvez intercepter les appels à SDL_Flip
ou SDL_UpdateRect
selon le cas.
Si elle charge OpenGL directement avec 'dlopen()', vous pouvez toujours remplacer la libGL.so dans/usr/lib par votre propre libGL.so, bien que votre solution soit probablement une solution plus simple. – Flexo
vous avez probablement raison. Je devrais entrer dans plus de codage C, je pense que je vais aller de l'avant avec ma solution. La performance n'est pas trop mauvaise, étonnamment. – user423805