qp.c (10186B)
1 // Copyright 2021 Nick Brassel (@tzarc) 2 // SPDX-License-Identifier: GPL-2.0-or-later 3 4 #include <quantum.h> 5 #include <utf8.h> 6 7 #include "qp_internal.h" 8 #include "qp_comms.h" 9 #include "qp_draw.h" 10 11 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 12 // Internal driver validation 13 14 static bool validate_driver_vtable(painter_driver_t *driver) { 15 return (driver && driver->driver_vtable && driver->driver_vtable->init && driver->driver_vtable->power && driver->driver_vtable->clear && driver->driver_vtable->viewport && driver->driver_vtable->pixdata && driver->driver_vtable->palette_convert && driver->driver_vtable->append_pixels && driver->driver_vtable->append_pixdata) ? true : false; 16 } 17 18 static bool validate_comms_vtable(painter_driver_t *driver) { 19 return (driver && driver->comms_vtable && driver->comms_vtable->comms_init && driver->comms_vtable->comms_start && driver->comms_vtable->comms_stop && driver->comms_vtable->comms_send) ? true : false; 20 } 21 22 static bool validate_driver_integrity(painter_driver_t *driver) { 23 return validate_driver_vtable(driver) && validate_comms_vtable(driver); 24 } 25 26 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 27 // Quantum Painter External API: qp_init 28 29 bool qp_init(painter_device_t device, painter_rotation_t rotation) { 30 qp_dprintf("qp_init: entry\n"); 31 painter_driver_t *driver = (painter_driver_t *)device; 32 33 if (!driver) { 34 qp_dprintf("qp_init: fail (pointer to NULL)\n"); 35 return false; 36 } 37 38 driver->validate_ok = false; 39 if (!validate_driver_integrity(driver)) { 40 qp_dprintf("Failed to validate driver integrity in qp_init\n"); 41 return false; 42 } 43 44 driver->validate_ok = true; 45 46 if (!qp_comms_init(device)) { 47 driver->validate_ok = false; 48 qp_dprintf("qp_init: fail (could not init comms)\n"); 49 return false; 50 } 51 52 if (!qp_comms_start(device)) { 53 qp_dprintf("qp_init: fail (could not start comms)\n"); 54 return false; 55 } 56 57 // Set the rotation before init 58 driver->rotation = rotation; 59 60 // Invoke init 61 bool ret = driver->driver_vtable->init(device, rotation); 62 qp_comms_stop(device); 63 qp_dprintf("qp_init: %s\n", ret ? "ok" : "fail"); 64 return ret; 65 } 66 67 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 68 // Quantum Painter External API: qp_power 69 70 bool qp_power(painter_device_t device, bool power_on) { 71 qp_dprintf("qp_power: entry\n"); 72 painter_driver_t *driver = (painter_driver_t *)device; 73 if (!driver || !driver->validate_ok) { 74 qp_dprintf("qp_power: fail (validation_ok == false)\n"); 75 return false; 76 } 77 78 if (!qp_comms_start(device)) { 79 qp_dprintf("qp_power: fail (could not start comms)\n"); 80 return false; 81 } 82 83 bool ret = driver->driver_vtable->power(device, power_on); 84 qp_comms_stop(device); 85 qp_dprintf("qp_power: %s\n", ret ? "ok" : "fail"); 86 return ret; 87 } 88 89 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 90 // Quantum Painter External API: qp_clear 91 92 bool qp_clear(painter_device_t device) { 93 qp_dprintf("qp_clear: entry\n"); 94 painter_driver_t *driver = (painter_driver_t *)device; 95 if (!driver || !driver->validate_ok) { 96 qp_dprintf("qp_clear: fail (validation_ok == false)\n"); 97 return false; 98 } 99 100 if (!qp_comms_start(device)) { 101 qp_dprintf("qp_clear: fail (could not start comms)\n"); 102 return false; 103 } 104 105 bool ret = driver->driver_vtable->clear(device); 106 qp_comms_stop(device); 107 qp_dprintf("qp_clear: %s\n", ret ? "ok" : "fail"); 108 return ret; 109 } 110 111 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 112 // Quantum Painter External API: qp_flush 113 114 bool qp_flush(painter_device_t device) { 115 qp_dprintf("qp_flush: entry\n"); 116 painter_driver_t *driver = (painter_driver_t *)device; 117 if (!driver || !driver->validate_ok) { 118 qp_dprintf("qp_flush: fail (validation_ok == false)\n"); 119 return false; 120 } 121 122 if (!qp_comms_start(device)) { 123 qp_dprintf("qp_flush: fail (could not start comms)\n"); 124 return false; 125 } 126 127 bool ret = driver->driver_vtable->flush(device); 128 qp_comms_stop(device); 129 qp_dprintf("qp_flush: %s\n", ret ? "ok" : "fail"); 130 return ret; 131 } 132 133 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 134 // Quantum Painter External API: qp_get_* 135 136 uint16_t qp_get_width(painter_device_t device) { 137 qp_dprintf("qp_get_width: entry\n"); 138 painter_driver_t *driver = (painter_driver_t *)device; 139 140 if (!driver || !driver->validate_ok) { 141 qp_dprintf("qp_get_width: fail (invalid driver)\n"); 142 return 0; 143 } 144 145 uint16_t width; 146 switch (driver->rotation) { 147 default: 148 case QP_ROTATION_0: 149 case QP_ROTATION_180: 150 width = driver->panel_width; 151 break; 152 case QP_ROTATION_90: 153 case QP_ROTATION_270: 154 width = driver->panel_height; 155 break; 156 } 157 158 qp_dprintf("qp_get_width: ok\n"); 159 return width; 160 } 161 162 uint16_t qp_get_height(painter_device_t device) { 163 qp_dprintf("qp_get_height: entry\n"); 164 painter_driver_t *driver = (painter_driver_t *)device; 165 166 if (!driver || !driver->validate_ok) { 167 qp_dprintf("qp_get_height: fail (invalid driver)\n"); 168 return 0; 169 } 170 171 uint16_t height; 172 switch (driver->rotation) { 173 default: 174 case QP_ROTATION_0: 175 case QP_ROTATION_180: 176 height = driver->panel_height; 177 break; 178 case QP_ROTATION_90: 179 case QP_ROTATION_270: 180 height = driver->panel_width; 181 break; 182 } 183 184 qp_dprintf("qp_get_height: ok\n"); 185 return height; 186 } 187 188 painter_rotation_t qp_get_rotation(painter_device_t device) { 189 qp_dprintf("qp_get_rotation: entry\n"); 190 painter_driver_t *driver = (painter_driver_t *)device; 191 192 if (!driver || !driver->validate_ok) { 193 qp_dprintf("qp_get_rotation: fail (invalid driver)\n"); 194 return QP_ROTATION_0; 195 } 196 197 qp_dprintf("qp_get_rotation: ok\n"); 198 return driver->rotation; 199 } 200 201 uint16_t qp_get_offset_x(painter_device_t device) { 202 qp_dprintf("qp_get_offset_x: entry\n"); 203 painter_driver_t *driver = (painter_driver_t *)device; 204 205 if (!driver || !driver->validate_ok) { 206 qp_dprintf("qp_get_offset_x: fail (invalid driver)\n"); 207 return 0; 208 } 209 210 qp_dprintf("qp_get_offset_x: ok\n"); 211 return driver->offset_x; 212 } 213 214 uint16_t qp_get_offset_y(painter_device_t device) { 215 qp_dprintf("qp_get_offset_y: entry\n"); 216 painter_driver_t *driver = (painter_driver_t *)device; 217 218 if (!driver || !driver->validate_ok) { 219 qp_dprintf("qp_get_offset_y: fail (invalid driver)\n"); 220 return 0; 221 } 222 223 qp_dprintf("qp_get_offset_y: ok\n"); 224 return driver->offset_y; 225 } 226 227 void qp_get_geometry(painter_device_t device, uint16_t *width, uint16_t *height, painter_rotation_t *rotation, uint16_t *offset_x, uint16_t *offset_y) { 228 qp_dprintf("qp_geometry: entry\n"); 229 painter_driver_t *driver = (painter_driver_t *)device; 230 231 if (!driver || !driver->validate_ok) { 232 qp_dprintf("qp_geometry: fail (invalid driver)\n"); 233 return; 234 } 235 236 if (width) { 237 *width = qp_get_width(device); 238 } 239 240 if (height) { 241 *height = qp_get_height(device); 242 } 243 244 if (rotation) { 245 *rotation = qp_get_rotation(device); 246 } 247 248 if (offset_x) { 249 *offset_x = qp_get_offset_x(device); 250 } 251 252 if (offset_y) { 253 *offset_y = qp_get_offset_y(device); 254 } 255 256 qp_dprintf("qp_get_geometry: ok\n"); 257 } 258 259 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 260 // Quantum Painter External API: qp_set_viewport_offsets 261 262 void qp_set_viewport_offsets(painter_device_t device, uint16_t offset_x, uint16_t offset_y) { 263 qp_dprintf("qp_set_viewport_offsets: entry\n"); 264 painter_driver_t *driver = (painter_driver_t *)device; 265 266 if (!driver) { 267 qp_dprintf("qp_set_viewport_offsets: fail (pointer to NULL)\n"); 268 return; 269 } 270 271 driver->offset_x = offset_x; 272 driver->offset_y = offset_y; 273 274 qp_dprintf("qp_set_viewport_offsets: ok\n"); 275 } 276 277 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 278 // Quantum Painter External API: qp_viewport 279 280 bool qp_viewport(painter_device_t device, uint16_t left, uint16_t top, uint16_t right, uint16_t bottom) { 281 qp_dprintf("qp_viewport: entry\n"); 282 painter_driver_t *driver = (painter_driver_t *)device; 283 if (!driver || !driver->validate_ok) { 284 qp_dprintf("qp_viewport: fail (validation_ok == false)\n"); 285 return false; 286 } 287 288 if (!qp_comms_start(device)) { 289 qp_dprintf("qp_viewport: fail (could not start comms)\n"); 290 return false; 291 } 292 293 // Set the viewport 294 bool ret = driver->driver_vtable->viewport(device, left, top, right, bottom); 295 qp_dprintf("qp_viewport: %s\n", ret ? "ok" : "fail"); 296 qp_comms_stop(device); 297 return ret; 298 } 299 300 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 301 // Quantum Painter External API: qp_pixdata 302 303 bool qp_pixdata(painter_device_t device, const void *pixel_data, uint32_t native_pixel_count) { 304 qp_dprintf("qp_pixdata: entry\n"); 305 painter_driver_t *driver = (painter_driver_t *)device; 306 if (!driver || !driver->validate_ok) { 307 qp_dprintf("qp_pixdata: fail (validation_ok == false)\n"); 308 return false; 309 } 310 311 if (!qp_comms_start(device)) { 312 qp_dprintf("qp_pixdata: fail (could not start comms)\n"); 313 return false; 314 } 315 316 bool ret = driver->driver_vtable->pixdata(device, pixel_data, native_pixel_count); 317 qp_dprintf("qp_pixdata: %s\n", ret ? "ok" : "fail"); 318 qp_comms_stop(device); 319 return ret; 320 }