static jboolean fbDispmanRobotScreenCapture(jint x, jint y, jint width, jint height, jint *pixels) { FILE *fb; unsigned int *pixelBuffer = NULL; unsigned char *pixelBufferPtr = NULL; unsigned char *dst = (unsigned char *) pixels; int i = 0; int fbFileHandle; struct fb_var_screeninfo screenInfo; unsigned int dstByteStride = width * 4; VC_IMAGE_TRANSFORM_T transform = 0; DISPMANX_RESOURCE_HANDLE_T resource = 0; DISPMANX_DISPLAY_HANDLE_T display = 0; DISPMANX_RESOURCE_HANDLE_T screenResource = 0; uint32_t imagePtr; int rc; GLASS_LOG_FINE("Capture %i,%i+%ix%i", x, y, width, height); if (width < 1 || height < 1) { GLASS_LOG_SEVERE("Failed. width/height values must be at least = 1"); return JNI_FALSE; } GLASS_LOG_FINE("open(%s, O_RDONLY)", FB_DEVICE); fbFileHandle = open(FB_DEVICE, O_RDONLY); if (fbFileHandle < 0) { GLASS_LOG_SEVERE("Cannot open framebuffer"); return JNI_FALSE; } GLASS_LOG_FINE("ioctl(%s, FBIOGET_VSCREENINFO)", FB_DEVICE); if (ioctl(fbFileHandle, FBIOGET_VSCREENINFO, &screenInfo)) { GLASS_LOG_SEVERE("Cannot get screen info"); GLASS_LOG_FINE("close(%s)", FB_DEVICE); close(fbFileHandle); return JNI_FALSE; } GLASS_LOG_FINE("Read screen info: res=%ix%i, offset=%ix%i", screenInfo.xres, screenInfo.yres, screenInfo.xoffset, screenInfo.yoffset); GLASS_LOG_FINE("close(%s)", FB_DEVICE); close(fbFileHandle); VC_RECT_T pixelRect = { 0, 0, screenInfo.xres, screenInfo.yres }; int pixelBufferLength = screenInfo.xres * screenInfo.yres * 4; pixelBuffer = (unsigned int *) malloc(pixelBufferLength); pixelBufferPtr = (unsigned char *) pixelBuffer; if (pixelBuffer == NULL) { printf("Failed to allocate temporary pixel buffer\n"); return JNI_FALSE; } GLASS_LOG_FINE("fopen(%s, \"r\") to read %ix%i pixels at bit depth %i\n", FB_DEVICE, width, height, screenInfo.bits_per_pixel); display = vc_dispmanx_display_open(0 /* LCD */); if (display == 0) { fprintf(stderr, "fbRobotScreenCapture: Dispman: Cannot open display\n"); free(pixelBuffer); return JNI_FALSE; } // create the resource for the snapshot screenResource = vc_dispmanx_resource_create(VC_IMAGE_ARGB8888, screenInfo.xres, screenInfo.yres, &imagePtr); if (!screenResource) { fprintf(stderr, "fbRobotScreenCapture: Cannot create resource\n"); vc_dispmanx_display_close(display); free(pixelBuffer); return JNI_FALSE; } rc = vc_dispmanx_snapshot(display, screenResource, transform); rc = 0; if (rc) { fprintf(stderr, "fbRobotScreenCapture: snapshot failed\n"); vc_dispmanx_display_close(display); free(pixelBuffer); return JNI_FALSE; } rc = vc_dispmanx_resource_read_data(screenResource, &pixelRect, pixelBuffer, screenInfo.xres * 4); if (rc) { fprintf(stderr, "fbRobotScreenCapture: Cannot read pixels %d\n", rc); vc_dispmanx_display_close(display); free(pixelBuffer); return JNI_FALSE; } rc = vc_dispmanx_resource_delete(screenResource); if (rc) { fprintf(stderr, "fbRobotScreenCapture: failed to free buffer %d\n", rc); vc_dispmanx_display_close(display); free(pixelBuffer); return JNI_FALSE; } screenResource = 0; if (x < 0) { pixelBuffer += -x; width += x; x = 0; } if (y < 0) { pixelBuffer += -y * (int)screenInfo.xres; height += y; y = 0; } int widthLimit = width; int heightLimit = height; // Required height is larger than screen's height if ((int) screenInfo.yres < height) { heightLimit = (int) screenInfo.yres; } // Required width is larger than screen's width if ((int) screenInfo.xres < width) { widthLimit = (int) screenInfo.xres; } // Required height is out of range if (((int) screenInfo.yres - y) < height) { heightLimit = (int) screenInfo.yres - y; } // Required width is out of range if (((int) screenInfo.xres - x) < width) { widthLimit = (int) screenInfo.xres - x; } if (widthLimit > 0 && heightLimit > 0) { // copy the relevant portion of the screen to the supplied pixel array int offset = y * screenInfo.xres * 4 + x * 4; for (i = 0; i < heightLimit; i++) { memcpy(dst + i * dstByteStride, pixelBufferPtr + offset, widthLimit * 4); offset += screenInfo.xres * 4; } } else { GLASS_LOG_SEVERE("Failed to take a snapshot, some of parameters are illegal"); free(pixelBuffer); return JNI_FALSE; } vc_dispmanx_display_close(display); free(pixelBuffer); return JNI_TRUE; }
static void initIDs(JNIEnv *env) { if (haveIDs) { return; } GLASS_LOG_FINE("Setting up JNI references"); haveIDs = 1; // screen specific jScreenClass = (*env)->NewGlobalRef(env, (*env)->FindClass(env, "com/sun/glass/ui/Screen")); CHECK_AND_RET_VOID(env); //LensApplication jLensApplicationClass = (*env)->NewGlobalRef(env, (*env)->FindClass(env, "com/sun/glass/ui/lens/LensApplication")); CHECK_AND_RET_VOID(env); jLensApplication_notifyKeyEvent = (*env)->GetMethodID(env, jLensApplicationClass, "notifyKeyEvent", "(Lcom/sun/glass/ui/lens/LensView;III[C)V"); jLensApplication_notifyMouseEvent = (*env)->GetMethodID( env, jLensApplicationClass, "notifyMouseEvent", "(Lcom/sun/glass/ui/lens/LensView;IIIIIIIZZ)V"); jLensApplication_notifyScrollEvent = (*env)->GetMethodID( env, jLensApplicationClass, "notifyScrollEvent", "(Lcom/sun/glass/ui/lens/LensView;IIIIDDIIIIIDD)V"); jLensApplication_notifyTouchEvent = (*env)->GetMethodID( env, jLensApplicationClass, "notifyTouchEvent", "(Lcom/sun/glass/ui/lens/LensView;IJIIII)V"); jLensApplication_notifyMultiTouchEvent = (*env)->GetMethodID( env, jLensApplicationClass, "notifyMultiTouchEvent", "(Lcom/sun/glass/ui/lens/LensView;[I[J[I[III)V"); jLensApplication_notifyWindowResize = (*env)->GetMethodID(env, jLensApplicationClass, "notifyWindowResize", "(Lcom/sun/glass/ui/lens/LensWindow;III)V"); jLensApplication_notifyWindowMove = (*env)->GetMethodID(env, jLensApplicationClass, "notifyWindowMove", "(Lcom/sun/glass/ui/lens/LensWindow;II)V"); jLensApplication_createNativeEventThread = (*env)->GetStaticMethodID(env, jLensApplicationClass, "createNativeEventThread", "(JJ)V"); jLensApplication_waitEventLoopsToFinish = (*env)->GetStaticMethodID(env, jLensApplicationClass, "waitEventLoopsToFinish", "()V"); jLensApplication_notifyWindowEvent = (*env)->GetMethodID(env, jLensApplicationClass, "notifyWindowEvent", "(Lcom/sun/glass/ui/lens/LensWindow;I)V"); jLensApplication_notifyViewEvent = (*env)->GetMethodID(env, jLensApplicationClass, "notifyViewEvent", "(Lcom/sun/glass/ui/lens/LensView;IIIII)V"); jLensApplication_notifyDeviceEvent = (*env)->GetMethodID(env, jLensApplicationClass, "notifyDeviceEvent", "(IZ)V"); jLensApplication_notifyScreenSettingsChanged = (*env)->GetMethodID(env, jLensApplicationClass, "notifyScreenSettingsChanged", "()V"); jLensApplication_notifyMenuEvent = (*env)->GetMethodID(env, jLensApplicationClass, "notifyMenuEvent", "(Lcom/sun/glass/ui/lens/LensView;IIIIZ)V"); jLensApplication_reportException = (*env)->GetStaticMethodID(env, jLensApplicationClass, "reportException", "(Ljava/lang/Throwable;)V"); CHECK_AND_RET_VOID(env); jGlassWindowClass = (*env)->NewGlobalRef(env, (*env)->FindClass(env, "com/sun/glass/ui/Window")); CHECK_AND_RET_VOID(env); jGlassWindowClass_Add = (*env)->GetStaticMethodID(env, jGlassWindowClass, "add", "(Lcom/sun/glass/ui/Window;)V"); CHECK_AND_RET_VOID(env); jGlassWindowClass_Remove = (*env)->GetStaticMethodID(env, jGlassWindowClass, "remove", "(Lcom/sun/glass/ui/Window;)V"); GLASS_LOG_FINE("Set up JNI references"); }
jboolean fbFBRobotScreen(jint x, jint y, jint width, jint height, jint *pixels) { FILE *fb; unsigned char *pixelBuffer = NULL; unsigned char *dst = (unsigned char *) pixels; unsigned int dstByteStride = width * 4; int i = 0; int fbFileHandle; struct fb_var_screeninfo screenInfo; int depth; // pixel size in bytes GLASS_LOG_FINE("Capture %i,%i+%ix%i", x, y, width, height); jboolean result = JNI_FALSE; if (width < 1 || height < 1) { GLASS_LOG_SEVERE("Failed. width/height values must be at least = 1"); return JNI_FALSE; } GLASS_LOG_FINE("open(%s, O_RDONLY)", FB_DEVICE); fbFileHandle = open(FB_DEVICE, O_RDONLY); if (fbFileHandle < 0) { GLASS_LOG_SEVERE("Cannot open framebuffer"); return JNI_FALSE; } GLASS_LOG_FINE("ioctl(%s, FBIOGET_VSCREENINFO)", FB_DEVICE); if (ioctl(fbFileHandle, FBIOGET_VSCREENINFO, &screenInfo)) { GLASS_LOG_SEVERE("Cannot get screen info"); return JNI_FALSE; } GLASS_LOG_FINE("Read screen info: res=%ix%i, offset=%ix%i", screenInfo.xres, screenInfo.yres, screenInfo.xoffset, screenInfo.yoffset); GLASS_LOG_FINE("close(%s)", FB_DEVICE); close(fbFileHandle); depth = screenInfo.bits_per_pixel / 8; int pixelBufferLength = screenInfo.xres * screenInfo.yres * depth; pixelBuffer = (unsigned char *) malloc(pixelBufferLength); if (pixelBuffer == NULL) { GLASS_LOG_SEVERE("Failed to allocate temporary pixel buffer"); return JNI_FALSE; } GLASS_LOG_FINE("fopen(%s, \"r\") to read %ix%i pixels at bit depth %i", FB_DEVICE, width, height, screenInfo.bits_per_pixel); fb = fopen(FB_DEVICE, "r"); if (fb == NULL) { GLASS_LOG_SEVERE("FB: Cannot open framebuffer for reading"); free(pixelBuffer); return JNI_FALSE; } fseek(fb, screenInfo.yoffset * screenInfo.xres * depth, SEEK_SET); int numRead = fread(pixelBuffer, 1, pixelBufferLength, fb); if (x < 0) { dst += -x * 4; width += x; x = 0; } if (y < 0) { dst += -y * dstByteStride; height += y; y = 0; } int widthLimit = width; int heightLimit = height; // Required height is larger than screen's height if ((int) screenInfo.yres < height) { heightLimit = (int) screenInfo.yres; } // Required width is larger than screen's width if ((int) screenInfo.xres < width) { widthLimit = (int) screenInfo.xres; } // Required height is out of range if (((int) screenInfo.yres - y) < height) { heightLimit = (int) screenInfo.yres - y; } // Required width is out of range if (((int) screenInfo.xres - x) < width) { widthLimit = (int) screenInfo.xres - x; } if (widthLimit > 0 && heightLimit > 0) { // copy the relevant portion of the screen to the supplied pixel array int offset = y * screenInfo.xres * depth + x * depth; for (i = 0; i < heightLimit; i++) { memcpy(dst + i * dstByteStride, pixelBuffer + offset, widthLimit * depth); offset += screenInfo.xres * depth; } } else { free(pixelBuffer); fclose(fb); GLASS_LOG_FINE("fclose(%s)", FB_DEVICE); GLASS_LOG_SEVERE("Failed to take a snapshot, some of parameters are illegal"); return JNI_FALSE; } free(pixelBuffer); GLASS_LOG_FINE("fclose(%s)", FB_DEVICE); fclose(fb); return JNI_TRUE; }