diff options
author | William Wilgus <wilgus.william@gmail.com> | 2020-10-07 02:01:35 -0400 |
---|---|---|
committer | William Wilgus <wilgus.william@gmail.com> | 2020-10-26 12:28:48 -0400 |
commit | 3237ae4a4ff9296a377ff9194a11038da161208f (patch) | |
tree | af4338c78467b9b0845d76c39da1fbe10f25e23e /firmware/drivers/lcd-bitmap-common.c | |
parent | 12f3ed1699d6bef25bed90ba95cbcc1a6bb4934a (diff) | |
download | rockbox-3237ae4a4ff9296a377ff9194a11038da161208f.tar.gz rockbox-3237ae4a4ff9296a377ff9194a11038da161208f.zip |
LCD core move buf ptr and address look up function viewport struct
I'm currently running up against the limitations of the lcd_draw functions
I want these functions to be able to be used on any size buffer not
just buffers with a stride matching the underlying device
[DONE] allow the framebuffer to be decoupled from the device framebuffer
[DONE need examples] allow for some simple blit like transformations
[DONE] remove the device framebuffer from the plugin api
[DONE}ditto remote framebuffer
[DONE] remove _viewport_get_framebuffer you can call struct *vp = lcd_set_viewport(NULL) and vp->buffer->fb_ptr
while remote lcds may compile (and work in the sim) its not been tested on targets
[FIXED] backdrops need work to be screen agnostic
[FIXED] screen statusbar is not being combined into the main viewport correctly yet
[FIXED] screen elements are displayed incorrectly after switch to void*
[FIXED] core didn't restore proper viewport on splash etc.
[NEEDS TESTING] remote lcd garbled data
[FIXED] osd lib garbled screen on bmp_part
[FIXED] grey_set_vp needs to return old viewport like lcd_set_viewport
[FIXED] Viewport update now handles viewports with differing buffers/strides by copying to the main buffer
[FIXED] splash on top of WPS leaves old framebuffer data (doesn't redraw)
[UPDATE] refined this a bit more to have clear_viewport set the clean bit and have skin_render do its own screen clear
scrolling viewports no longer trigger wps refresh
also fixed a bug where guisyncyesno was displaying and then disappearing
[ADDED!] New LCD macros that allow you to create properly size frame buffers in you desired size without wasting bytes
(LCD_ and LCD_REMOTE_)
LCD_STRIDE(w, h) same as STRIDE_MAIN
LCD_FBSTRIDE(w, h) returns target specific stride for a buffer W x H
LCD_NBELEMS(w, h) returns the number of fb_data sized elemenst needed for a buffer W x H
LCD_NATIVE_STRIDE(s) conversion between rockbox native vertical and lcd native stride (2bitH)
test_viewports.c has an example of usage
[FIXED!!] 2bit targets don't respect non-native strides
[FIXED] Few define snags
Change-Id: I0d04c3834e464eca84a5a715743a297a0cefd0af
Diffstat (limited to 'firmware/drivers/lcd-bitmap-common.c')
-rw-r--r-- | firmware/drivers/lcd-bitmap-common.c | 166 |
1 files changed, 115 insertions, 51 deletions
diff --git a/firmware/drivers/lcd-bitmap-common.c b/firmware/drivers/lcd-bitmap-common.c index 8c38e513c6..94829b5d0c 100644 --- a/firmware/drivers/lcd-bitmap-common.c +++ b/firmware/drivers/lcd-bitmap-common.c | |||
@@ -40,43 +40,70 @@ | |||
40 | #define MAIN_LCD | 40 | #define MAIN_LCD |
41 | #endif | 41 | #endif |
42 | 42 | ||
43 | void LCDFN(set_framebuffer)(FBFN(data) *fb) | 43 | #ifdef MAIN_LCD |
44 | { | 44 | #define THIS_STRIDE STRIDE_MAIN |
45 | if (fb) | 45 | #else |
46 | LCDFN(framebuffer) = fb; | 46 | #define THIS_STRIDE STRIDE_REMOTE |
47 | else | 47 | #endif |
48 | LCDFN(framebuffer) = &LCDFN(static_framebuffer)[0][0]; | ||
49 | } | ||
50 | 48 | ||
49 | extern void viewport_set_buffer(struct viewport *vp, | ||
50 | struct frame_buffer_t *buffer, | ||
51 | const enum screen_type screen); /* viewport.c */ | ||
51 | /* | 52 | /* |
52 | * draws the borders of the current viewport | 53 | * draws the borders of the current viewport |
53 | **/ | 54 | **/ |
54 | void LCDFN(draw_border_viewport)(void) | 55 | void LCDFN(draw_border_viewport)(void) |
55 | { | 56 | { |
56 | LCDFN(drawrect)(0, 0, current_vp->width, current_vp->height); | 57 | LCDFN(drawrect)(0, 0, LCDFN(current_viewport)->width, LCDFN(current_viewport)->height); |
57 | } | 58 | } |
58 | 59 | ||
59 | /* | 60 | /* |
60 | * fills the rectangle formed by current_vp | 61 | * fills the rectangle formed by LCDFN(current_viewport) |
61 | **/ | 62 | **/ |
62 | void LCDFN(fill_viewport)(void) | 63 | void LCDFN(fill_viewport)(void) |
63 | { | 64 | { |
64 | LCDFN(fillrect)(0, 0, current_vp->width, current_vp->height); | 65 | LCDFN(fillrect)(0, 0, LCDFN(current_viewport)->width, LCDFN(current_viewport)->height); |
65 | } | 66 | } |
66 | 67 | ||
67 | 68 | ||
68 | /*** Viewports ***/ | 69 | /*** Viewports ***/ |
69 | 70 | /* init_viewport Notes: When a viewport is initialized | |
70 | void LCDFN(set_viewport)(struct viewport* vp) | 71 | * if vp->buffer is NULL the default frame_buffer is assigned |
72 | * likewise the actual buffer, stride, get_address_fn | ||
73 | * are all filled with values from the default buffer if they are not set | ||
74 | * RETURNS either the viewport you passed or the default viewport if vp == NULL | ||
75 | */ | ||
76 | struct viewport* LCDFN(init_viewport)(struct viewport* vp) | ||
71 | { | 77 | { |
72 | if (vp == NULL) | 78 | struct frame_buffer_t *fb_default = &LCDFN(framebuffer_default); |
73 | current_vp = &default_vp; | 79 | if (!vp) /* NULL vp grabs default viewport */ |
80 | vp = &default_vp; | ||
81 | |||
82 | /* use defaults if no buffer is provided */ | ||
83 | if (vp->buffer == NULL || vp->buffer->elems == 0) | ||
84 | vp->buffer = fb_default; | ||
74 | else | 85 | else |
75 | current_vp = vp; | 86 | { |
87 | if (vp->buffer->stride == 0) | ||
88 | vp->buffer->stride = fb_default->stride; | ||
89 | |||
90 | if (vp->buffer->data == NULL) | ||
91 | vp->buffer->data = fb_default->data; | ||
92 | |||
93 | if (vp->buffer->get_address_fn == NULL) | ||
94 | vp->buffer->get_address_fn = fb_default->get_address_fn; | ||
95 | } | ||
96 | return vp; | ||
97 | } | ||
98 | struct viewport* LCDFN(set_viewport_ex)(struct viewport* vp, int flags) | ||
99 | { | ||
100 | vp = LCDFN(init_viewport)(vp); | ||
101 | struct viewport* last_vp = LCDFN(current_viewport); | ||
102 | LCDFN(current_viewport) = vp; | ||
76 | 103 | ||
77 | #if LCDM(DEPTH) > 1 | 104 | #if LCDM(DEPTH) > 1 |
78 | LCDFN(set_foreground)(current_vp->fg_pattern); | 105 | LCDFN(set_foreground)(vp->fg_pattern); |
79 | LCDFN(set_background)(current_vp->bg_pattern); | 106 | LCDFN(set_background)(vp->bg_pattern); |
80 | #endif | 107 | #endif |
81 | 108 | ||
82 | #if defined(SIMULATOR) | 109 | #if defined(SIMULATOR) |
@@ -84,10 +111,11 @@ void LCDFN(set_viewport)(struct viewport* vp) | |||
84 | * be considered an error - the viewport will not draw as it might be | 111 | * be considered an error - the viewport will not draw as it might be |
85 | * expected. | 112 | * expected. |
86 | */ | 113 | */ |
87 | if((unsigned) current_vp->x > (unsigned) LCDM(WIDTH) | 114 | |
88 | || (unsigned) current_vp->y > (unsigned) LCDM(HEIGHT) | 115 | if((unsigned) vp->x > (unsigned) LCDM(WIDTH) |
89 | || current_vp->x + current_vp->width > LCDM(WIDTH) | 116 | || (unsigned) vp->y > (unsigned) LCDM(HEIGHT) |
90 | || current_vp->y + current_vp->height > LCDM(HEIGHT)) | 117 | || vp->x + vp->width > LCDM(WIDTH) |
118 | || vp->y + vp->height > LCDM(HEIGHT)) | ||
91 | { | 119 | { |
92 | #if !defined(HAVE_VIEWPORT_CLIP) | 120 | #if !defined(HAVE_VIEWPORT_CLIP) |
93 | DEBUGF("ERROR: " | 121 | DEBUGF("ERROR: " |
@@ -95,27 +123,68 @@ void LCDFN(set_viewport)(struct viewport* vp) | |||
95 | DEBUGF("NOTE: " | 123 | DEBUGF("NOTE: " |
96 | #endif | 124 | #endif |
97 | "set_viewport out of bounds: x: %d y: %d width: %d height:%d\n", | 125 | "set_viewport out of bounds: x: %d y: %d width: %d height:%d\n", |
98 | current_vp->x, current_vp->y, | 126 | vp->x, vp->y, vp->width, vp->height); |
99 | current_vp->width, current_vp->height); | ||
100 | } | 127 | } |
101 | #endif | 128 | #endif |
129 | if(last_vp) | ||
130 | { | ||
131 | if ((flags & VP_FLAG_CLEAR_FLAG) == VP_FLAG_CLEAR_FLAG) | ||
132 | last_vp->flags &= ~flags; | ||
133 | else | ||
134 | last_vp->flags |= flags; | ||
135 | } | ||
136 | |||
137 | return last_vp; | ||
138 | } | ||
139 | |||
140 | struct viewport* LCDFN(set_viewport)(struct viewport* vp) | ||
141 | { | ||
142 | return LCDFN(set_viewport_ex)(vp, VP_FLAG_VP_DIRTY); | ||
102 | } | 143 | } |
103 | 144 | ||
104 | struct viewport *LCDFN(get_viewport)(bool *is_default) | 145 | struct viewport *LCDFN(get_viewport)(bool *is_default) |
105 | { | 146 | { |
106 | *is_default = (current_vp == &default_vp); | 147 | #if 0 |
107 | return current_vp; | 148 | *is_default = memcmp(LCDFN(current_viewport), |
149 | &default_vp, sizeof(struct viewport)) == 0; | ||
150 | #else | ||
151 | *is_default = LCDFN(current_viewport) == &default_vp; | ||
152 | #endif | ||
153 | |||
154 | return LCDFN(current_viewport); | ||
108 | } | 155 | } |
109 | 156 | ||
110 | void LCDFN(update_viewport)(void) | 157 | void LCDFN(update_viewport)(void) |
111 | { | 158 | { |
112 | LCDFN(update_rect)(current_vp->x, current_vp->y, | 159 | struct viewport* vp = LCDFN(current_viewport); |
113 | current_vp->width, current_vp->height); | 160 | if (vp->buffer->stride != LCDFN(framebuffer_default.stride)) |
161 | { | ||
162 | LCDFN(update_viewport_rect)(0,0, vp->width, vp->height); | ||
163 | return; | ||
164 | } | ||
165 | LCDFN(update_rect)(vp->x, vp->y, vp->width, vp->height); | ||
114 | } | 166 | } |
115 | 167 | ||
116 | void LCDFN(update_viewport_rect)(int x, int y, int width, int height) | 168 | void LCDFN(update_viewport_rect)(int x, int y, int width, int height) |
117 | { | 169 | { |
118 | LCDFN(update_rect)(current_vp->x + x, current_vp->y + y, width, height); | 170 | struct viewport* vp = LCDFN(current_viewport); |
171 | |||
172 | /* handle the case of viewport with differing stride from main screen */ | ||
173 | if (vp->buffer->stride != LCDFN(framebuffer_default.stride)) | ||
174 | { | ||
175 | struct frame_buffer_t *fb = vp->buffer; | ||
176 | viewport_set_buffer(vp, NULL, 0); | ||
177 | |||
178 | LCDFN(bitmap_part) | ||
179 | (fb->FBFN(ptr), vp->x, vp->y, fb->stride, | ||
180 | vp->x + x, vp->y + y, width, height); | ||
181 | |||
182 | LCDFN(update_rect)(vp->x + x, vp->y + y, width, height); | ||
183 | viewport_set_buffer(vp, fb, 0); | ||
184 | return; | ||
185 | } | ||
186 | |||
187 | LCDFN(update_rect)(vp->x + x, vp->y + y, width, height); | ||
119 | } | 188 | } |
120 | 189 | ||
121 | #ifndef BOOTLOADER | 190 | #ifndef BOOTLOADER |
@@ -123,9 +192,9 @@ void LCDFN(update_viewport_rect)(int x, int y, int width, int height) | |||
123 | static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str) | 192 | static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str) |
124 | { | 193 | { |
125 | unsigned short *ucs; | 194 | unsigned short *ucs; |
126 | font_lock(current_vp->font, true); | 195 | font_lock(LCDFN(current_viewport)->font, true); |
127 | struct font* pf = font_get(current_vp->font); | 196 | struct font* pf = font_get(LCDFN(current_viewport)->font); |
128 | int vp_flags = current_vp->flags; | 197 | int vp_flags = LCDFN(current_viewport)->flags; |
129 | int rtl_next_non_diac_width, last_non_diacritic_width; | 198 | int rtl_next_non_diac_width, last_non_diacritic_width; |
130 | 199 | ||
131 | if ((vp_flags & VP_FLAG_ALIGNMENT_MASK) != 0) | 200 | if ((vp_flags & VP_FLAG_ALIGNMENT_MASK) != 0) |
@@ -136,13 +205,13 @@ static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str) | |||
136 | /* center takes precedence */ | 205 | /* center takes precedence */ |
137 | if (vp_flags & VP_FLAG_ALIGN_CENTER) | 206 | if (vp_flags & VP_FLAG_ALIGN_CENTER) |
138 | { | 207 | { |
139 | x = ((current_vp->width - w)/ 2) + x; | 208 | x = ((LCDFN(current_viewport)->width - w)/ 2) + x; |
140 | if (x < 0) | 209 | if (x < 0) |
141 | x = 0; | 210 | x = 0; |
142 | } | 211 | } |
143 | else | 212 | else |
144 | { | 213 | { |
145 | x = current_vp->width - w - x; | 214 | x = LCDFN(current_viewport)->width - w - x; |
146 | x += ofs; | 215 | x += ofs; |
147 | ofs = 0; | 216 | ofs = 0; |
148 | } | 217 | } |
@@ -158,7 +227,7 @@ static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str) | |||
158 | int width, base_width, drawmode = 0, base_ofs = 0; | 227 | int width, base_width, drawmode = 0, base_ofs = 0; |
159 | const unsigned short next_ch = ucs[1]; | 228 | const unsigned short next_ch = ucs[1]; |
160 | 229 | ||
161 | if (x >= current_vp->width) | 230 | if (x >= LCDFN(current_viewport)->width) |
162 | break; | 231 | break; |
163 | 232 | ||
164 | is_diac = is_diacritic(*ucs, &is_rtl); | 233 | is_diac = is_diacritic(*ucs, &is_rtl); |
@@ -219,8 +288,8 @@ static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str) | |||
219 | * buffer using OR, and then draw the final bitmap instead of the | 288 | * buffer using OR, and then draw the final bitmap instead of the |
220 | * chars, without touching the drawmode | 289 | * chars, without touching the drawmode |
221 | **/ | 290 | **/ |
222 | drawmode = current_vp->drawmode; | 291 | drawmode = LCDFN(current_viewport)->drawmode; |
223 | current_vp->drawmode = DRMODE_FG; | 292 | LCDFN(current_viewport)->drawmode = DRMODE_FG; |
224 | 293 | ||
225 | base_ofs = (base_width - width) / 2; | 294 | base_ofs = (base_width - width) / 2; |
226 | } | 295 | } |
@@ -237,7 +306,7 @@ static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str) | |||
237 | y, width - ofs, pf->height); | 306 | y, width - ofs, pf->height); |
238 | if (is_diac) | 307 | if (is_diac) |
239 | { | 308 | { |
240 | current_vp->drawmode = drawmode; | 309 | LCDFN(current_viewport)->drawmode = drawmode; |
241 | } | 310 | } |
242 | 311 | ||
243 | if (next_ch) | 312 | if (next_ch) |
@@ -256,7 +325,7 @@ static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str) | |||
256 | } | 325 | } |
257 | } | 326 | } |
258 | } | 327 | } |
259 | font_lock(current_vp->font, false); | 328 | font_lock(LCDFN(current_viewport)->font, false); |
260 | } | 329 | } |
261 | #else /* BOOTLOADER */ | 330 | #else /* BOOTLOADER */ |
262 | /* put a string at a given pixel position, skipping first ofs pixel columns */ | 331 | /* put a string at a given pixel position, skipping first ofs pixel columns */ |
@@ -375,7 +444,7 @@ static struct scrollinfo* find_scrolling_line(int x, int y) | |||
375 | for(i=0; i<LCDFN(scroll_info).lines; i++) | 444 | for(i=0; i<LCDFN(scroll_info).lines; i++) |
376 | { | 445 | { |
377 | s = &LCDFN(scroll_info).scroll[i]; | 446 | s = &LCDFN(scroll_info).scroll[i]; |
378 | if (s->x == x && s->y == y && s->vp == current_vp) | 447 | if (s->x == x && s->y == y && s->vp == LCDFN(current_viewport)) |
379 | return s; | 448 | return s; |
380 | } | 449 | } |
381 | return NULL; | 450 | return NULL; |
@@ -411,13 +480,13 @@ static bool LCDFN(puts_scroll_worker)(int x, int y, const unsigned char *string, | |||
411 | 480 | ||
412 | /* prepare rectangle for scrolling. x and y must be calculated early | 481 | /* prepare rectangle for scrolling. x and y must be calculated early |
413 | * for find_scrolling_line() to work */ | 482 | * for find_scrolling_line() to work */ |
414 | cwidth = font_get(current_vp->font)->maxwidth; | 483 | cwidth = font_get(LCDFN(current_viewport)->font)->maxwidth; |
415 | height = font_get(current_vp->font)->height; | 484 | height = font_get(LCDFN(current_viewport)->font)->height; |
416 | y = y * (linebased ? height : 1); | 485 | y = y * (linebased ? height : 1); |
417 | x = x * (linebased ? cwidth : 1); | 486 | x = x * (linebased ? cwidth : 1); |
418 | width = current_vp->width - x; | 487 | width = LCDFN(current_viewport)->width - x; |
419 | 488 | ||
420 | if (y >= current_vp->height) | 489 | if (y >= LCDFN(current_viewport)->height) |
421 | return false; | 490 | return false; |
422 | 491 | ||
423 | s = find_scrolling_line(x, y); | 492 | s = find_scrolling_line(x, y); |
@@ -430,7 +499,7 @@ static bool LCDFN(puts_scroll_worker)(int x, int y, const unsigned char *string, | |||
430 | * the string width is too small to scroll the scrolling line is | 499 | * the string width is too small to scroll the scrolling line is |
431 | * cleared as well */ | 500 | * cleared as well */ |
432 | if (w < width || restart) { | 501 | if (w < width || restart) { |
433 | LCDFN(scroll_stop_viewport_rect)(current_vp, x, y, width, height); | 502 | LCDFN(scroll_stop_viewport_rect)(LCDFN(current_viewport), x, y, width, height); |
434 | LCDFN(putsxyofs)(x, y, x_offset, string); | 503 | LCDFN(putsxyofs)(x, y, x_offset, string); |
435 | /* nothing to scroll, or out of scrolling lines. Either way, get out */ | 504 | /* nothing to scroll, or out of scrolling lines. Either way, get out */ |
436 | if (w < width || LCDFN(scroll_info).lines >= LCDM(SCROLLABLE_LINES)) | 505 | if (w < width || LCDFN(scroll_info).lines >= LCDM(SCROLLABLE_LINES)) |
@@ -443,7 +512,7 @@ static bool LCDFN(puts_scroll_worker)(int x, int y, const unsigned char *string, | |||
443 | strlcpy(s->linebuffer, string, sizeof(s->linebuffer)); | 512 | strlcpy(s->linebuffer, string, sizeof(s->linebuffer)); |
444 | /* scroll bidirectional or forward only depending on the string width */ | 513 | /* scroll bidirectional or forward only depending on the string width */ |
445 | if ( LCDFN(scroll_info).bidir_limit ) { | 514 | if ( LCDFN(scroll_info).bidir_limit ) { |
446 | s->bidir = w < (current_vp->width) * | 515 | s->bidir = w < (LCDFN(current_viewport)->width) * |
447 | (100 + LCDFN(scroll_info).bidir_limit) / 100; | 516 | (100 + LCDFN(scroll_info).bidir_limit) / 100; |
448 | } | 517 | } |
449 | else | 518 | else |
@@ -457,7 +526,7 @@ static bool LCDFN(puts_scroll_worker)(int x, int y, const unsigned char *string, | |||
457 | s->y = y; | 526 | s->y = y; |
458 | s->width = width; | 527 | s->width = width; |
459 | s->height = height; | 528 | s->height = height; |
460 | s->vp = current_vp; | 529 | s->vp = LCDFN(current_viewport); |
461 | s->start_tick = current_tick + LCDFN(scroll_info).delay; | 530 | s->start_tick = current_tick + LCDFN(scroll_info).delay; |
462 | LCDFN(scroll_info).lines++; | 531 | LCDFN(scroll_info).lines++; |
463 | } else { | 532 | } else { |
@@ -497,11 +566,6 @@ bool LCDFN(puts_scroll)(int x, int y, const unsigned char *string) | |||
497 | 566 | ||
498 | #if !defined(HAVE_LCD_COLOR) || !defined(MAIN_LCD) | 567 | #if !defined(HAVE_LCD_COLOR) || !defined(MAIN_LCD) |
499 | /* see lcd-16bit-common.c for others */ | 568 | /* see lcd-16bit-common.c for others */ |
500 | #ifdef MAIN_LCD | ||
501 | #define THIS_STRIDE STRIDE_MAIN | ||
502 | #else | ||
503 | #define THIS_STRIDE STRIDE_REMOTE | ||
504 | #endif | ||
505 | 569 | ||
506 | void LCDFN(bmp_part)(const struct bitmap* bm, int src_x, int src_y, | 570 | void LCDFN(bmp_part)(const struct bitmap* bm, int src_x, int src_y, |
507 | int x, int y, int width, int height) | 571 | int x, int y, int width, int height) |