Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

expose flags on framebuffer #8

Open
darvin opened this issue May 19, 2018 · 4 comments
Open

expose flags on framebuffer #8

darvin opened this issue May 19, 2018 · 4 comments

Comments

@darvin
Copy link

darvin commented May 19, 2018

I'm using libremarkable to port Plato reader on remarkable, i need to pass EPDC_FLAG_ENABLE_INVERSION to update flags

@canselcik
Copy link
Owner

canselcik commented May 19, 2018

Hi,

If you look at the mxc_epdc_fb.c, which is the EPDC driver that our ioctl is handled by:

    /*
     * Set PxP LUT transform type based on update flags.
     */
    fb_data->pxp_conf.proc_data.lut_transform = 0;
    if (upd_desc_list->upd_data.flags & EPDC_FLAG_ENABLE_INVERSION)
        fb_data->pxp_conf.proc_data.lut_transform |= PXP_LUT_INVERT;
    if (upd_desc_list->upd_data.flags & EPDC_FLAG_FORCE_MONOCHROME)
        fb_data->pxp_conf.proc_data.lut_transform |=
            PXP_LUT_BLACK_WHITE;
    if (upd_desc_list->upd_data.flags & EPDC_FLAG_USE_CMAP)
        fb_data->pxp_conf.proc_data.lut_transform |=
            PXP_LUT_USE_CMAP;
    /*
     * If no processing required, skip update processing
     * No processing means:
     *   - FB unrotated
     *   - FB pixel format = 8-bit grayscale
     *   - No look-up transformations (inversion, posterization, etc.)
     *
     * Note: A bug with EPDC stride prevents us from skipping
     * PxP in versions 2.0 and earlier of EPDC.
     */
    is_transform = upd_data_list->update_desc->upd_data.flags &
                   (EPDC_FLAG_ENABLE_INVERSION | EPDC_FLAG_USE_DITHERING_Y1 |
                    EPDC_FLAG_USE_DITHERING_Y4 | EPDC_FLAG_FORCE_MONOCHROME |
                    EPDC_FLAG_USE_CMAP) ? true : false;

It looks like EPDC_FLAG_ENABLE_INVERSION is actually an EPDC_FLAG that's passed to the refresh ioctl inside the mxcfb_update_data that we provide to it. Therefore it is already exposed as a part of the Framebuffer::partial_refresh(..) and Framebuffer::full_refresh(..) under the flags parameter.

On the other hand, if you wanted to enable inversion for the entire framebuffer, regardless of the flags passed inside the mxcfb_update_data struct, this might be of interest to you:

    /*
     * Toggle inversion processing if 8-bit
     * inverted is the current pixel format.
     */
    if (fb_data->epdc_fb_var.grayscale == GRAYSCALE_8BIT_INVERTED)
        fb_data->pxp_conf.proc_data.lut_transform ^= PXP_LUT_INVERT;

As you can see, here the driver looks at the fb_var_screeninfo struct's grayscale field and checks if it is GRAYSCALE_8BIT_INVERTED. This is also exposed by libremarkable via the Framebuffer::get_var_screeninfo() and Framebuffer:put_var_screeninfo() methods.

For the latter, you'll want to update the contents of var_screen_info inside your Framebuffer.

@canselcik
Copy link
Owner

canselcik commented May 19, 2018

You could also create a new "constructor" for Framebuffer. The current implementation follows what xochitl would have done on the device:

fn new(path_to_device: &str) -> Framebuffer {
        let device = OpenOptions::new()
            .read(true)
            .write(true)
            .open(path_to_device)
            .unwrap();

        let mut var_screen_info = Framebuffer::get_var_screeninfo(&device);
        let fix_screen_info = Framebuffer::get_fix_screeninfo(&device);

        let frame_length = (fix_screen_info.line_length * var_screen_info.yres) as usize;
        let mem_map = MemoryMap::new(
            frame_length,
            &[
                mmap::MapOption::MapReadable,
                mmap::MapOption::MapWritable,
                mmap::MapOption::MapFd(device.as_raw_fd()),
                mmap::MapOption::MapOffset(0),
                mmap::MapOption::MapNonStandardFlags(libc::MAP_SHARED),
            ],
        ).unwrap();

        // Load the font
        let font_data = include_bytes!("../../assets/DejaVuSans.ttf");
        let collection = FontCollection::from_bytes(font_data as &[u8]);

        var_screen_info.xres = 1872;
        var_screen_info.yres = 1404;
        var_screen_info.rotate = 1;
        var_screen_info.width = var_screen_info.xres;
        var_screen_info.height = var_screen_info.yres;
        var_screen_info.pixclock = 160000000;
        var_screen_info.left_margin = 32;
        var_screen_info.right_margin = 326;
        var_screen_info.upper_margin = 4;
        var_screen_info.lower_margin = 12;
        var_screen_info.hsync_len = 44;
        var_screen_info.vsync_len = 1;
        var_screen_info.sync = 0;
        var_screen_info.vmode = 0; // FB_VMODE_NONINTERLACED
        var_screen_info.accel_flags = 0;
        let mut fb = Framebuffer {
            marker: AtomicU32::new(1),
            device,
            frame: mem_map,
            default_font: collection.into_font().unwrap(),
            var_screen_info,
            fix_screen_info,
        };
        if !fb.put_var_screeninfo() {
            panic!("FBIOPUT_VSCREENINFO failed");
        }
        return fb;
    }

I would be more than happy to merge a PR that creates an additional constructor that accepts more configurables.

@LinusCDE
Copy link
Collaborator

LinusCDE commented Sep 10, 2020

I also stumbled upon this when re-porting plato. Though I didn't deem the feature important enough and ignored using the flags.

I also had to do paste some of the constructor-code to get a proper rotation (RemarkableFrambuffer::set_rotation()).

This may also be a candidate to add to the this lib, since it tooks me a lot of hours to figure out why the framebuffer either didn't rotate or got all messed up, or clipped (addressed here which got merged with PR #37).

@LinusCDE
Copy link
Collaborator

This might be a nice feature to have. But since the rm2 prevents us to go that lowlevel anymore anyway (at least rn, maybe waved can change this), I doubt it would be useful to add custom flags anyway. The implementation should be easy enough though. Do we want to do this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants