// Feasibility check: can we intercept EPFramebuffer::setBuffers to capture the // framebuffer's backing QImages? setBuffers is called from the epaper platform // plugin (libepaper) into libqsgepaper — a cross-DSO call, so unlike swapBuffers // it should be interposable via LD_PRELOAD. If this fires and reports real image // dimensions + a pixel pointer, the direct-framebuffer ink pipeline is viable. // // ABI: std::tuple is non-trivially-copyable, so it's passed by // reference (a pointer); QImage* is a pointer. So three pointer args after this. #include #include #include #include extern "C" void _ZN13EPFramebuffer10setBuffersESt5tupleIJ6QImageS1_EEPS1_( void *self, void *tuplePtr, void *imgPtr) { static void (*real)(void *, void *, void *) = nullptr; if (!real) real = (void (*)(void *, void *, void *))dlsym( RTLD_NEXT, "_ZN13EPFramebuffer10setBuffersESt5tupleIJ6QImageS1_EEPS1_"); auto *t = reinterpret_cast *>(tuplePtr); QImage *c = reinterpret_cast(imgPtr); const QImage &a = std::get<0>(*t); const QImage &b = std::get<1>(*t); fprintf(stderr, "SETBUFFERS self=%p | A=%dx%d fmt=%d bytesPerLine=%d cbits=%p | " "B=%dx%d fmt=%d | C=%p %dx%d\n", self, a.width(), a.height(), int(a.format()), a.bytesPerLine(), (const void *)a.constBits(), b.width(), b.height(), int(b.format()), (void *)c, c ? c->width() : -1, c ? c->height() : -1); if (real) real(self, tuplePtr, imgPtr); }