Hi all,
I am struggling for some time with the topic. Bottom line is that for one proprietary Android application we need to capture screenshots of the entire screen (not our activity) and push those images to VNC server. Now, I read various topics about (ab)using OpenGL ES for this cause but never found complete code with initialization (in C++). What I tried basically are some variants of the following code:
const EGLint attribs[] = {
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, //important
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_NONE
};
EGLint attribList[] =
{
EGL_CONTEXT_CLIENT_VERSION, 3,
EGL_NONE
};
EGLint w, h, dummy, format;
EGLint numConfigs;
EGLConfig config;
EGLSurface surface;
EGLContext context;
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
EGLBoolean res = eglInitialize(display, 0, 0);
log << "eglInitialize: " << (res ? "yes": "no") << " " << eglGetError() << "
";
EGLint pi32ConfigAttribs[] =
{
EGL_SURFACE_TYPE,
EGL_PBUFFER_BIT,
EGL_RENDERABLE_TYPE,
EGL_OPENGL_BIT,
EGL_CONFORMANT,
EGL_OPENGL_BIT,
EGL_COLOR_BUFFER_TYPE,
EGL_RGB_BUFFER,
EGL_LUMINANCE_SIZE,
0,
EGL_RED_SIZE,
8,
EGL_GREEN_SIZE,
8,
EGL_BLUE_SIZE,
8,
EGL_ALPHA_SIZE,
8,
EGL_DEPTH_SIZE,
8,
EGL_LEVEL,
0,
EGL_BUFFER_SIZE,
24,
EGL_NONE
};
res = eglChooseConfig(display, pi32ConfigAttribs, &config, 1, &numConfigs);
log << "eglChooseConfig: " << (res ? "yes" : "no") << " " << eglGetError() << "
";
// res = eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
// log << "eglGetConfigAttrib: " << (res ? "yes" : "no") << " " << eglGetError() << "
";
// ANativeWindow* window;
// ANativeWindow_setBuffersGeometry(window, 0, 0, format);
// log << "window: " << (window != 0 ? "yes": "no") << "
";
EGLint pbufferAttribs[5];
pbufferAttribs[0] = EGL_WIDTH;
pbufferAttribs[1] = 200;
pbufferAttribs[2] = EGL_HEIGHT;
pbufferAttribs[3] = 200;
pbufferAttribs[4] = EGL_NONE;
surface = eglCreatePbufferSurface(display, config, pbufferAttribs);
log << "surface: " << (surface ? "yes" : "no") << " " << eglGetError() << "
";
context = eglCreateContext(display, config, NULL, attribList);
log << "context: " << (context ? "yes" : "no") << " " << eglGetError() << "
";
res = eglMakeCurrent(display, surface, surface, context);
log << "eglMakeCurrent: " << (res ? "yes": "no") << " " << eglGetError() << "
";
GLubyte *texture = new GLubyte[screenSize.width() * screenSize.height() * bpp]; // 3 for RGB, 4 for RGBA
glReadBuffer(GL_FRONT);
glReadPixels(0, 0, screenSize.width(), screenSize.height(), GL_RGB, GL_UNSIGNED_BYTE, texture);
On Linux I had no such troubles at all, and simply used:
Display *dpy = XOpenDisplay(nullptr);
Display *dpy = XOpenDisplay(nullptr);
Window root = DefaultRootWindow(dpy);
GLint att[] = {GLX_RGBA, 0};
XVisualInfo *vis = glXChooseVisual(dpy, 0, att);
GLXContext glc = glXCreateContext(dpy, vis, nullptr, true);
GLubyte *texture = new GLubyte[screenSize.width() * screenSize.height() * bpp]; // 3 for RGB, 4 for RGBA
glXMakeCurrent(dpy, root, glc);
glReadBuffer(GL_FRONT);
glReadPixels(0, 0, screenSize.width(), screenSize.height(), GL_RGB, GL_UNSIGNED_BYTE, texture);
So in short - is this possible to do? I also considered using the framebuffer, but as I understood it is not always available and possibly you need to have rooted phone.
Thank you all in advance