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");
}
예제 #3
0
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;
}