diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/drivers/lcd-16bit-common.c | 168 |
1 files changed, 72 insertions, 96 deletions
diff --git a/firmware/drivers/lcd-16bit-common.c b/firmware/drivers/lcd-16bit-common.c index b9c9060216..1b84847929 100644 --- a/firmware/drivers/lcd-16bit-common.c +++ b/firmware/drivers/lcd-16bit-common.c | |||
@@ -283,12 +283,6 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, | |||
283 | int src_y, int stride, int x, int y, | 283 | int src_y, int stride, int x, int y, |
284 | int width, int height) | 284 | int width, int height) |
285 | { | 285 | { |
286 | const unsigned char *src_end; | ||
287 | fb_data *dst, *dst_col; | ||
288 | unsigned dmask = 0x100; /* bit 8 == sentinel */ | ||
289 | int drmode = lcd_current_viewport->drawmode; | ||
290 | int row; | ||
291 | |||
292 | /******************** Image in viewport clipping **********************/ | 286 | /******************** Image in viewport clipping **********************/ |
293 | /* nothing to draw? */ | 287 | /* nothing to draw? */ |
294 | if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || | 288 | if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || |
@@ -312,22 +306,10 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, | |||
312 | if (y + height > lcd_current_viewport->height) | 306 | if (y + height > lcd_current_viewport->height) |
313 | height = lcd_current_viewport->height - y; | 307 | height = lcd_current_viewport->height - y; |
314 | 308 | ||
315 | /* adjust for viewport */ | 309 | /* convert to viewport coordinates */ |
316 | x += lcd_current_viewport->x; | 310 | x += lcd_current_viewport->x; |
317 | y += lcd_current_viewport->y; | 311 | y += lcd_current_viewport->y; |
318 | 312 | ||
319 | /* 'Bugfix' mono_bitmap_part reads ahead in the buffer, While this is a bug | ||
320 | * if the height is <= char bit pixels other memory gets read but is not used | ||
321 | * the other option is to check in the hot code path but this appears | ||
322 | * sufficient, limit to the sim to stop Address Sanitizer errors | ||
323 | */ | ||
324 | #if defined(SIMULATOR) && \ | ||
325 | (!defined(LCD_STRIDEFORMAT) || LCD_STRIDEFORMAT != VERTICAL_STRIDE) | ||
326 | /* vertical stride targets don't seem affected by this */ | ||
327 | if (height <= CHAR_BIT) | ||
328 | stride = 0; | ||
329 | #endif | ||
330 | |||
331 | #if defined(HAVE_VIEWPORT_CLIP) | 313 | #if defined(HAVE_VIEWPORT_CLIP) |
332 | /********************* Viewport on screen clipping ********************/ | 314 | /********************* Viewport on screen clipping ********************/ |
333 | /* nothing to draw? */ | 315 | /* nothing to draw? */ |
@@ -342,7 +324,6 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, | |||
342 | src_x -= x; | 324 | src_x -= x; |
343 | x = 0; | 325 | x = 0; |
344 | } | 326 | } |
345 | |||
346 | if (y < 0) | 327 | if (y < 0) |
347 | { | 328 | { |
348 | height += y; | 329 | height += y; |
@@ -354,14 +335,17 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, | |||
354 | if (y + height > LCD_HEIGHT) | 335 | if (y + height > LCD_HEIGHT) |
355 | height = LCD_HEIGHT - y; | 336 | height = LCD_HEIGHT - y; |
356 | #endif | 337 | #endif |
357 | src += stride * (src_y >> 3) + src_x; /* move starting point */ | 338 | |
358 | src_y &= 7; | 339 | /* move starting point */ |
359 | src_end = src + width; | 340 | src += stride * (src_y >> 3) + src_x; |
360 | dst_col = FBADDR(x, y); | 341 | src_y &= 7; |
342 | |||
343 | unsigned dmask = 0; | ||
344 | int drmode = lcd_current_viewport->drawmode; | ||
361 | 345 | ||
362 | if (drmode & DRMODE_INVERSEVID) | 346 | if (drmode & DRMODE_INVERSEVID) |
363 | { | 347 | { |
364 | dmask = 0x1ff; /* bit 8 == sentinel */ | 348 | dmask = 0xff; |
365 | drmode &= DRMODE_SOLID; /* mask out inversevid */ | 349 | drmode &= DRMODE_SOLID; /* mask out inversevid */ |
366 | } | 350 | } |
367 | 351 | ||
@@ -369,107 +353,99 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, | |||
369 | if ((drmode & DRMODE_BG) && lcd_backdrop) | 353 | if ((drmode & DRMODE_BG) && lcd_backdrop) |
370 | drmode |= DRMODE_INT_BD; | 354 | drmode |= DRMODE_INT_BD; |
371 | 355 | ||
372 | /* go through each column and update each pixel */ | 356 | fb_data* dst = FBADDR(x, y); |
373 | do | 357 | while(height > 0) |
374 | { | 358 | { |
375 | const unsigned char *src_col = src++; | 359 | const unsigned char* src_col = src; |
376 | unsigned data = (*src_col ^ dmask) >> src_y; | 360 | const unsigned char* src_end = src + width; |
361 | fb_data* dst_col = dst; | ||
362 | |||
363 | unsigned data; | ||
377 | int fg, bg; | 364 | int fg, bg; |
378 | uintptr_t bo; | 365 | uintptr_t bo; |
379 | 366 | ||
380 | dst = dst_col; | 367 | switch (drmode) { |
381 | dst_col += COL_INC; | 368 | case DRMODE_COMPLEMENT: |
382 | row = height; | 369 | do { |
383 | 370 | data = (*src_col++ ^ dmask) >> src_y; | |
384 | #define UPDATE_SRC do { \ | 371 | if(data & 0x01) |
385 | data >>= 1; \ | 372 | *dst_col = ~(*dst_col); |
386 | if (data == 0x001) { \ | ||
387 | src_col += stride; \ | ||
388 | data = *src_col ^ dmask; \ | ||
389 | } \ | ||
390 | } while (0) | ||
391 | |||
392 | switch (drmode) | ||
393 | { | ||
394 | case DRMODE_COMPLEMENT: | ||
395 | do | ||
396 | { | ||
397 | if (data & 0x01) | ||
398 | *dst = ~(*dst); | ||
399 | 373 | ||
400 | dst += ROW_INC; | 374 | dst_col += COL_INC; |
401 | UPDATE_SRC; | 375 | } while(src_col != src_end); |
402 | } | ||
403 | while (--row); | ||
404 | break; | 376 | break; |
405 | 377 | ||
406 | case DRMODE_BG|DRMODE_INT_BD: | 378 | case DRMODE_BG|DRMODE_INT_BD: |
407 | bo = lcd_backdrop_offset; | 379 | bo = lcd_backdrop_offset; |
408 | do | 380 | do { |
409 | { | 381 | data = (*src_col++ ^ dmask) >> src_y; |
410 | if (!(data & 0x01)) | 382 | if(!(data & 0x01)) |
411 | *dst = *PTR_ADD(dst, bo); | 383 | *dst_col = *PTR_ADD(dst_col, bo); |
412 | 384 | ||
413 | dst += ROW_INC; | 385 | dst_col += COL_INC; |
414 | UPDATE_SRC; | 386 | } while(src_col != src_end); |
415 | } | ||
416 | while (--row); | ||
417 | break; | 387 | break; |
418 | 388 | ||
419 | case DRMODE_BG: | 389 | case DRMODE_BG: |
420 | bg = lcd_current_viewport->bg_pattern; | 390 | bg = lcd_current_viewport->bg_pattern; |
421 | do | 391 | do { |
422 | { | 392 | data = (*src_col++ ^ dmask) >> src_y; |
423 | if (!(data & 0x01)) | 393 | if(!(data & 0x01)) |
424 | *dst = bg; | 394 | *dst_col = bg; |
425 | 395 | ||
426 | dst += ROW_INC; | 396 | dst_col += COL_INC; |
427 | UPDATE_SRC; | 397 | } while(src_col != src_end); |
428 | } | ||
429 | while (--row); | ||
430 | break; | 398 | break; |
431 | 399 | ||
432 | case DRMODE_FG: | 400 | case DRMODE_FG: |
433 | fg = lcd_current_viewport->fg_pattern; | 401 | fg = lcd_current_viewport->fg_pattern; |
434 | do | 402 | do { |
435 | { | 403 | data = (*src_col++ ^ dmask) >> src_y; |
436 | if (data & 0x01) | 404 | if(data & 0x01) |
437 | *dst = fg; | 405 | *dst_col = fg; |
438 | 406 | ||
439 | dst += ROW_INC; | 407 | dst_col += COL_INC; |
440 | UPDATE_SRC; | 408 | } while(src_col != src_end); |
441 | } | ||
442 | while (--row); | ||
443 | break; | 409 | break; |
444 | 410 | ||
445 | case DRMODE_SOLID|DRMODE_INT_BD: | 411 | case DRMODE_SOLID|DRMODE_INT_BD: |
446 | fg = lcd_current_viewport->fg_pattern; | 412 | fg = lcd_current_viewport->fg_pattern; |
447 | bo = lcd_backdrop_offset; | 413 | bo = lcd_backdrop_offset; |
448 | do | 414 | do { |
449 | { | 415 | data = (*src_col++ ^ dmask) >> src_y; |
450 | *dst = (data & 0x01) ? fg | 416 | if(data & 0x01) |
451 | : *PTR_ADD(dst, bo); | 417 | *dst_col = fg; |
452 | dst += ROW_INC; | 418 | else |
453 | UPDATE_SRC; | 419 | *dst_col = *PTR_ADD(dst_col, bo); |
454 | } | 420 | |
455 | while (--row); | 421 | dst_col += COL_INC; |
422 | } while(src_col != src_end); | ||
456 | break; | 423 | break; |
457 | 424 | ||
458 | case DRMODE_SOLID: | 425 | case DRMODE_SOLID: |
459 | fg = lcd_current_viewport->fg_pattern; | 426 | fg = lcd_current_viewport->fg_pattern; |
460 | bg = lcd_current_viewport->bg_pattern; | 427 | bg = lcd_current_viewport->bg_pattern; |
461 | do | 428 | do { |
462 | { | 429 | data = (*src_col++ ^ dmask) >> src_y; |
463 | *dst = (data & 0x01) ? fg : bg; | 430 | if(data & 0x01) |
464 | dst += ROW_INC; | 431 | *dst_col = fg; |
465 | UPDATE_SRC; | 432 | else |
466 | } | 433 | *dst_col = bg; |
467 | while (--row); | 434 | |
435 | dst_col += COL_INC; | ||
436 | } while(src_col != src_end); | ||
468 | break; | 437 | break; |
469 | } | 438 | } |
439 | |||
440 | src_y = (src_y + 1) & 7; | ||
441 | if(src_y == 0) | ||
442 | src += stride; | ||
443 | |||
444 | dst += ROW_INC; | ||
445 | height--; | ||
470 | } | 446 | } |
471 | while (src < src_end); | ||
472 | } | 447 | } |
448 | |||
473 | /* Draw a full monochrome bitmap */ | 449 | /* Draw a full monochrome bitmap */ |
474 | void lcd_mono_bitmap(const unsigned char *src, int x, int y, int width, int height) | 450 | void lcd_mono_bitmap(const unsigned char *src, int x, int y, int width, int height) |
475 | { | 451 | { |