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