static void fbDispmanAddDispmanxElement(void) { DISPMANX_DISPLAY_HANDLE_T display = 0; DISPMANX_UPDATE_HANDLE_T update; VC_DISPMANX_ALPHA_T alpha; VC_RECT_T dst; VC_RECT_T src = { 0, 0, cursor.cursorWidth << 16, cursor.cursorHeight << 16}; VC_RECT_T pixelRect = { 0, 0, cursor.cursorWidth, cursor.cursorHeight }; int rc; display = vc_dispmanx_display_open(0 /* LCD */); if (display == 0) { GLASS_LOG_SEVERE("Cannot open display"); return; } update = vc_dispmanx_update_start(0); alpha.flags = DISPMANX_FLAGS_ALPHA_FROM_SOURCE; alpha.opacity = 0xff; alpha.mask = (DISPMANX_RESOURCE_HANDLE_T) 0; dst.x = cursor.x; dst.y = cursor.y; dst.width = cursor.cursorWidth; dst.height = cursor.cursorHeight; cursor.element = vc_dispmanx_element_add( update, display, 2 /*layer*/, &dst, 0 /*resource*/, &src, DISPMANX_PROTECTION_NONE, &alpha, 0 /*clamp*/, 0 /*transform*/); vc_dispmanx_update_submit_sync(update); }
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 jlong fbDispmanCreateNativeCursor(JNIEnv *env, jint x, jint y, jbyte *srcArray, jint width, jint height) { VC_RECT_T pixelRect; int rc; uint32_t imagePtr; jbyte *allocatedBuffer = NULL; DispmanCursorImage *cursorImage = (DispmanCursorImage *)malloc(sizeof(DispmanCursorImage)); //Width should be aligned to 16 pixels if (width % 16 != 0) { int newWidth = width + 16 - (width % 16); allocatedBuffer = (jbyte *)malloc(newWidth * height * 4); int i; int offset = 0; for (i = 0; i < height; ++i) { memcpy(allocatedBuffer + offset, srcArray, width * 4); memset(allocatedBuffer + offset + (width * 4), 0, (newWidth - width) * 4); offset += newWidth * 4; srcArray += width * 4; } width = newWidth; srcArray = allocatedBuffer; } pixelRect.x = 0; pixelRect.y = 0; pixelRect.width = width; pixelRect.height = height; cursorImage->x = x; cursorImage->y = y; cursorImage->width = width; cursorImage->height = height; cursorImage->resource = vc_dispmanx_resource_create(VC_IMAGE_ARGB8888, width, height, &imagePtr); if (cursorImage->resource == 0) { GLASS_LOG_SEVERE("Cannot create resource"); if (allocatedBuffer != NULL) { free(allocatedBuffer); allocatedBuffer = NULL; } free(cursorImage); return 0; } rc = vc_dispmanx_resource_write_data(cursorImage->resource, VC_IMAGE_ARGB8888, width * 4, srcArray, &pixelRect); if (allocatedBuffer != NULL) { free(allocatedBuffer); allocatedBuffer = NULL; } if (rc != 0) { GLASS_LOG_SEVERE("Cannot write pixels"); free(cursorImage); return 0; } return ptr_to_jlong(cursorImage); }
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; }