qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

qp_surface_mono1bpp.c (4687B)


      1 // Copyright 2022 Nick Brassel (@tzarc)
      2 // SPDX-License-Identifier: GPL-2.0-or-later
      3 
      4 #ifdef QUANTUM_PAINTER_SURFACE_ENABLE
      5 
      6 #    include "color.h"
      7 #    include "qp_draw.h"
      8 #    include "qp_surface_internal.h"
      9 #    include "qp_comms_dummy.h"
     10 
     11 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     12 // Surface driver impl: mono1bpp
     13 
     14 static inline void setpixel_mono1bpp(surface_painter_device_t *surface, uint16_t x, uint16_t y, bool mono_pixel) {
     15     uint16_t w = surface->base.panel_width;
     16     uint16_t h = surface->base.panel_height;
     17 
     18     // Drop out if it's off-screen
     19     if (x >= w || y >= h) {
     20         return;
     21     }
     22 
     23     // Figure out which location needs to be updated
     24     uint32_t pixel_num   = y * w + x;
     25     uint32_t byte_offset = pixel_num / 8;
     26     uint8_t  bit_offset  = pixel_num % 8;
     27     bool     curr_val    = (surface->u8buffer[byte_offset] & (1 << bit_offset)) ? true : false;
     28 
     29     // Skip messing with the dirty info if the original value already matches
     30     if (curr_val != mono_pixel) {
     31         // Update the dirty region
     32         qp_surface_update_dirty(&surface->dirty, x, y);
     33 
     34         // Update the pixel data in the buffer
     35         if (mono_pixel) {
     36             surface->u8buffer[byte_offset] |= (1 << bit_offset);
     37         } else {
     38             surface->u8buffer[byte_offset] &= ~(1 << bit_offset);
     39         }
     40     }
     41 }
     42 
     43 static inline void append_pixel_mono1bpp(surface_painter_device_t *surface, bool mono_pixel) {
     44     setpixel_mono1bpp(surface, surface->viewport.pixdata_x, surface->viewport.pixdata_y, mono_pixel);
     45     qp_surface_increment_pixdata_location(&surface->viewport);
     46 }
     47 
     48 static inline void stream_pixdata_mono1bpp(surface_painter_device_t *surface, const uint8_t *data, uint32_t native_pixel_count) {
     49     for (uint32_t pixel_counter = 0; pixel_counter < native_pixel_count; ++pixel_counter) {
     50         uint32_t byte_offset = pixel_counter / 8;
     51         uint8_t  bit_offset  = pixel_counter % 8;
     52         append_pixel_mono1bpp(surface, (data[byte_offset] & (1 << bit_offset)) ? true : false);
     53     }
     54 }
     55 
     56 // Stream pixel data to the current write position in GRAM
     57 static bool qp_surface_pixdata_mono1bpp(painter_device_t device, const void *pixel_data, uint32_t native_pixel_count) {
     58     painter_driver_t         *driver  = (painter_driver_t *)device;
     59     surface_painter_device_t *surface = (surface_painter_device_t *)driver;
     60     stream_pixdata_mono1bpp(surface, (const uint8_t *)pixel_data, native_pixel_count);
     61     return true;
     62 }
     63 
     64 // Pixel colour conversion
     65 static bool qp_surface_palette_convert_mono1bpp(painter_device_t device, int16_t palette_size, qp_pixel_t *palette) {
     66     for (int16_t i = 0; i < palette_size; ++i) {
     67         palette[i].mono = (palette[i].hsv888.v > 127) ? 1 : 0;
     68     }
     69     return true;
     70 }
     71 
     72 // Append pixels to the target location, keyed by the pixel index
     73 static bool qp_surface_append_pixels_mono1bpp(painter_device_t device, uint8_t *target_buffer, qp_pixel_t *palette, uint32_t pixel_offset, uint32_t pixel_count, uint8_t *palette_indices) {
     74     for (uint32_t i = 0; i < pixel_count; ++i) {
     75         uint32_t pixel_num   = pixel_offset + i;
     76         uint32_t byte_offset = pixel_num / 8;
     77         uint8_t  bit_offset  = pixel_num % 8;
     78         if (palette[palette_indices[i]].mono) {
     79             target_buffer[byte_offset] |= (1 << bit_offset);
     80         } else {
     81             target_buffer[byte_offset] &= ~(1 << bit_offset);
     82         }
     83     }
     84     return true;
     85 }
     86 
     87 static bool mono1bpp_target_pixdata_transfer(painter_driver_t *surface_driver, painter_driver_t *target_driver, uint16_t x, uint16_t y, bool entire_surface) {
     88     return false; // Not yet supported.
     89 }
     90 
     91 static bool qp_surface_append_pixdata_mono1bpp(painter_device_t device, uint8_t *target_buffer, uint32_t pixdata_offset, uint8_t pixdata_byte) {
     92     return false; // Just use 1bpp images.
     93 }
     94 
     95 const surface_painter_driver_vtable_t mono1bpp_surface_driver_vtable = {
     96     .base =
     97         {
     98             .init            = qp_surface_init,
     99             .power           = qp_surface_power,
    100             .clear           = qp_surface_clear,
    101             .flush           = qp_surface_flush,
    102             .pixdata         = qp_surface_pixdata_mono1bpp,
    103             .viewport        = qp_surface_viewport,
    104             .palette_convert = qp_surface_palette_convert_mono1bpp,
    105             .append_pixels   = qp_surface_append_pixels_mono1bpp,
    106             .append_pixdata  = qp_surface_append_pixdata_mono1bpp,
    107         },
    108     .target_pixdata_transfer = mono1bpp_target_pixdata_transfer,
    109 };
    110 
    111 SURFACE_FACTORY_FUNCTION_IMPL(qp_make_mono1bpp_surface, mono1bpp_surface_driver_vtable, 1);
    112 
    113 #endif // QUANTUM_PAINTER_SURFACE_ENABLE