diff options
Diffstat (limited to 'apps/plugins/lib/osd.c')
-rw-r--r-- | apps/plugins/lib/osd.c | 778 |
1 files changed, 580 insertions, 198 deletions
diff --git a/apps/plugins/lib/osd.c b/apps/plugins/lib/osd.c index ff0533a898..598a76759c 100644 --- a/apps/plugins/lib/osd.c +++ b/apps/plugins/lib/osd.c | |||
@@ -21,6 +21,7 @@ | |||
21 | * | 21 | * |
22 | ****************************************************************************/ | 22 | ****************************************************************************/ |
23 | #include "plugin.h" | 23 | #include "plugin.h" |
24 | #include "grey.h" | ||
24 | #include "osd.h" | 25 | #include "osd.h" |
25 | 26 | ||
26 | #if 1 | 27 | #if 1 |
@@ -28,10 +29,20 @@ | |||
28 | #define DEBUGF(...) | 29 | #define DEBUGF(...) |
29 | #endif | 30 | #endif |
30 | 31 | ||
32 | #if defined(SIMULATOR) && LCD_DEPTH < 4 | ||
33 | /* Sim isn't using --ffunction-sections thus greylib references will happen | ||
34 | here even if not using this with greylib on a grayscale display, which | ||
35 | demands that a struct _grey_info exist. */ | ||
36 | #ifndef _WIN32 | ||
37 | __attribute__((weak)) | ||
38 | #endif /* _WIN32 */ | ||
39 | struct _grey_info _grey_info; | ||
40 | #endif /* defined(SIMULATOR) && LCD_DEPTH < 4 */ | ||
41 | |||
31 | /* At this time: assumes use of the default viewport for normal drawing */ | 42 | /* At this time: assumes use of the default viewport for normal drawing */ |
32 | 43 | ||
33 | /* If multiple OSD's are wanted, could convert to caller-allocated */ | 44 | /* If multiple OSD's are wanted, could convert to caller-allocated */ |
34 | static struct osd | 45 | struct osd |
35 | { | 46 | { |
36 | enum osd_status | 47 | enum osd_status |
37 | { | 48 | { |
@@ -41,152 +52,314 @@ static struct osd | |||
41 | OSD_ERASED, /* Erased in preparation for regular drawing */ | 52 | OSD_ERASED, /* Erased in preparation for regular drawing */ |
42 | } status; /* View status */ | 53 | } status; /* View status */ |
43 | struct viewport vp; /* Clipping viewport */ | 54 | struct viewport vp; /* Clipping viewport */ |
44 | struct bitmap lcd_bitmap; /* The main LCD fb bitmap */ | 55 | int lcd_bitmap_stride; /* Stride of LCD bitmap */ |
45 | struct bitmap back_bitmap; /* The OSD backbuffer fb bitmap */ | 56 | void *lcd_bitmap_data; /* Backbuffer framebuffer data */ |
57 | int back_bitmap_stride; /* Stride of backbuffer bitmap */ | ||
58 | void *back_bitmap_data; /* LCD framebuffer data */ | ||
46 | int maxwidth; /* How wide may it be at most? */ | 59 | int maxwidth; /* How wide may it be at most? */ |
47 | int maxheight; /* How high may it be at most? */ | 60 | int maxheight; /* How high may it be at most? */ |
48 | long timeout; /* Current popup stay duration */ | 61 | long timeout; /* Current popup stay duration */ |
49 | long hide_tick; /* Tick when it should be hidden */ | 62 | long hide_tick; /* Tick when it should be hidden */ |
50 | osd_draw_cb_fn_t draw_cb; /* Draw update callback */ | 63 | osd_draw_cb_fn_t draw_cb; /* Draw update callback */ |
51 | } osd; | 64 | /* Functions to factilitate interface compatibility of OSD types */ |
65 | void * (*init_buffers)(struct osd *osd, unsigned flags, void *buf, | ||
66 | size_t *bufsize); | ||
67 | void (*set_viewport_pos)(struct viewport *vp, int x, int y, int width, | ||
68 | int height); | ||
69 | void (*lcd_update)(void); | ||
70 | void (*lcd_update_rect)(int x, int y, int width, int height); | ||
71 | void (*lcd_set_viewport)(struct viewport *vp); | ||
72 | void (*lcd_set_framebuffer)(void *buf); | ||
73 | void (*lcd_framebuffer_set_pos)(int x, int y, int width, int height); | ||
74 | void (*lcd_bitmap_part)(const void *src, int src_x, int src_y, | ||
75 | int stride, int x, int y, int width, int height); | ||
76 | }; | ||
77 | |||
78 | static struct osd native_osd; | ||
79 | #if LCD_DEPTH < 4 | ||
80 | static struct osd grey_osd; | ||
81 | #endif | ||
52 | 82 | ||
53 | /* Framebuffer allocation macros */ | 83 | /* Framebuffer allocation macros */ |
54 | #if LCD_DEPTH == 1 | 84 | #if LCD_DEPTH == 1 |
55 | # if LCD_PIXELFORMAT == HORIZONTAL_PACKING | 85 | # if LCD_PIXELFORMAT == HORIZONTAL_PACKING |
56 | # define LCD_WIDTH2BYTES(w) (((w)+7)/8) | 86 | # define _OSD_WIDTH2BYTES(w) (((w)+7)/8) |
57 | # define LCD_BYTES2WIDTH(b) ((b)*8) | 87 | # define _OSD_BYTES2WIDTH(b) ((b)*8) |
58 | # elif LCD_PIXELFORMAT == VERTICAL_PACKING | 88 | # elif LCD_PIXELFORMAT == VERTICAL_PACKING |
59 | # define LCD_HEIGHT2BYTES(h) (((h)+7)/8) | 89 | # define _OSD_HEIGHT2BYTES(h) (((h)+7)/8) |
60 | # define LCD_BYTES2HEIGHT(b) ((b)*8) | 90 | # define _OSD_BYTES2HEIGHT(b) ((b)*8) |
61 | # else | 91 | # else |
62 | # error Unknown 1-bit format; please define macros | 92 | # error Unknown 1-bit format; please define macros |
63 | # endif /* LCD_PIXELFORMAT */ | 93 | # endif /* LCD_PIXELFORMAT */ |
64 | #elif LCD_DEPTH == 2 | 94 | #elif LCD_DEPTH == 2 |
65 | # if LCD_PIXELFORMAT == HORIZONTAL_PACKING | 95 | # if LCD_PIXELFORMAT == HORIZONTAL_PACKING |
66 | # define LCD_WIDTH2BYTES(w) (((w)+3)/4) | 96 | # define _OSD_WIDTH2BYTES(w) (((w)+3)/4) |
67 | # define LCD_BYTES2WIDTH(b) ((b)*4) | 97 | # define _OSD_BYTES2WIDTH(b) ((b)*4) |
68 | # elif LCD_PIXELFORMAT == VERTICAL_PACKING | 98 | # elif LCD_PIXELFORMAT == VERTICAL_PACKING |
69 | # define LCD_HEIGHT2BYTES(h) (((h)+3)/4) | 99 | # define _OSD_HEIGHT2BYTES(h) (((h)+3)/4) |
70 | # define LCD_BYTES2HEIGHT(b) ((b)*4) | 100 | # define _OSD_BYTES2HEIGHT(b) ((b)*4) |
71 | # elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED | 101 | # elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED |
72 | # define LCD_WIDTH2BYTES(w) ((w)*2) | 102 | # define _OSD_HEIGHT2BYTES(h) (((h)+7)/8*2) |
73 | # define LCD_BYTES2WIDTH(b) ((b)/2) | 103 | # define _OSD_BYTES2HEIGHT(b) ((b)/2*8) |
74 | # define LCD_HEIGHT2BYTES(h) (((h)+7)/8*2) | ||
75 | # define LCD_BYTES2HEIGHT(b) ((b)/2*8) | ||
76 | # else | 104 | # else |
77 | # error Unknown 2-bit format; please define macros | 105 | # error Unknown 2-bit format; please define macros |
78 | # endif /* LCD_PIXELFORMAT */ | 106 | # endif /* LCD_PIXELFORMAT */ |
79 | #elif LCD_DEPTH == 16 | 107 | #elif LCD_DEPTH == 16 |
80 | # define LCD_WIDTH2BYTES(w) ((w)*2) | 108 | # if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE |
81 | # define LCD_BYTES2WIDTH(b) ((b)/2) | 109 | # define _OSD_HEIGHT2BYTES(h) ((h)*2) |
82 | #else | 110 | # define _OSD_BYTES2HEIGHT(b) ((b)/2) |
111 | # else /* !defined(LCD_STRIDEFORMAT) || LCD_STRIDEFORMAT != VERTICAL_STRIDE */ | ||
112 | # define _OSD_WIDTH2BYTES(w) ((w)*2) | ||
113 | # define _OSD_BYTES2WIDTH(b) ((b)/2) | ||
114 | # endif /* end stride type selection */ | ||
115 | #else /* other LCD depth */ | ||
83 | # error Unknown LCD depth; please define macros | 116 | # error Unknown LCD depth; please define macros |
84 | #endif /* LCD_DEPTH */ | 117 | #endif /* LCD_DEPTH */ |
85 | /* Set defaults if not defined different yet. */ | 118 | /* Set defaults if not defined differently */ |
86 | #ifndef LCD_WIDTH2BYTES | 119 | #ifndef _OSD_WIDTH2BYTES |
87 | # define LCD_WIDTH2BYTES(w) (w) | 120 | # define _OSD_WIDTH2BYTES(w) (w) |
88 | #endif | 121 | #endif |
89 | #ifndef LCD_BYTES2WIDTH | 122 | #ifndef _OSD_BYTES2WIDTH |
90 | # define LCD_BYTES2WIDTH(b) (b) | 123 | # define _OSD_BYTES2WIDTH(b) (b) |
91 | #endif | 124 | #endif |
92 | #ifndef LCD_HEIGHT2BYTES | 125 | #ifndef _OSD_HEIGHT2BYTES |
93 | # define LCD_HEIGHT2BYTES(h) (h) | 126 | # define _OSD_HEIGHT2BYTES(h) (h) |
94 | #endif | 127 | #endif |
95 | #ifndef LCD_BYTES2HEIGHT | 128 | #ifndef _OSD_BYTES2HEIGHT |
96 | # define LCD_BYTES2HEIGHT(b) (b) | 129 | # define _OSD_BYTES2HEIGHT(b) (b) |
97 | #endif | 130 | #endif |
131 | #ifndef _OSD_BUFSIZE | ||
132 | # define _OSD_BUFSIZE(w, h) (_OSD_WIDTH2BYTES(w)*_OSD_HEIGHT2BYTES(h)) | ||
133 | #endif | ||
134 | |||
135 | static void _osd_destroy(struct osd *osd); | ||
136 | static bool _osd_show(struct osd *osd, unsigned flags); | ||
137 | |||
138 | |||
139 | /** Native LCD routines **/ | ||
98 | 140 | ||
99 | /* Create a bitmap framebuffer from a buffer */ | 141 | /* Create a bitmap framebuffer from a buffer */ |
100 | static fb_data * buf_to_fb_bitmap(void *buf, size_t bufsize, | 142 | static void * _osd_lcd_init_buffers(struct osd *osd, unsigned flags, |
101 | int *width, int *height) | 143 | void *buf, size_t *bufsize) |
102 | { | 144 | { |
103 | /* Used as dest, the LCD functions cannot deal with alternate | 145 | /* Used as dest, the LCD functions cannot deal with alternate |
104 | strides as of now - the stride guides the calulations. If | 146 | strides as of now - the stride guides the calulations. If |
105 | that is no longer the case, then width or height can be | 147 | that is no longer the case, then width or height can be |
106 | used instead (and less memory needed for a small surface!). | 148 | used instead (and less memory needed for a small surface!). |
149 | IOW: crappiness means one dimension is non-negotiable. | ||
107 | */ | 150 | */ |
108 | DEBUGF("buf: %p bufsize: %lu\n", buf, (unsigned long)bufsize); | 151 | DEBUGF("OSD: in(buf=%p bufsize=%lu)\n", buf, |
152 | (unsigned long)*bufsize); | ||
153 | |||
154 | rb->viewport_set_fullscreen(&osd->vp, SCREEN_MAIN); | ||
109 | 155 | ||
110 | #if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE | 156 | #if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE |
111 | int h = LCD_BYTES2HEIGHT(LCD_HEIGHT2BYTES(LCD_HEIGHT)); | 157 | int colbytes = _OSD_HEIGHT2BYTES(LCD_HEIGHT); |
112 | int w = bufsize / LCD_HEIGHT2BYTES(h); | 158 | int bytecols = *bufsize / colbytes; |
159 | int w = _OSD_BYTES2WIDTH(bytecols); | ||
160 | int h = _OSD_BYTES2HEIGHT(colbytes); | ||
113 | 161 | ||
114 | if (w == 0) | 162 | if (flags & OSD_INIT_MAJOR_HEIGHT) |
115 | { | 163 | { |
116 | DEBUGF("OSD: not enough buffer\n"); | 164 | if (w == 0 || ((flags & OSD_INIT_MINOR_MIN) && w < osd->maxwidth)) |
117 | return NULL; /* not enough buffer */ | 165 | { |
166 | DEBUGF("OSD: not enough buffer\n"); | ||
167 | return NULL; /* not enough buffer */ | ||
168 | } | ||
169 | |||
170 | if ((flags & OSD_INIT_MINOR_MAX) && w > osd->maxwidth) | ||
171 | w = osd->maxwidth; | ||
172 | } | ||
173 | else /* OSD_INIT_MAJOR_WIDTH implied */ | ||
174 | { | ||
175 | if (w == 0 || w < osd->maxwidth) | ||
176 | { | ||
177 | DEBUGF("OSD: not enough buffer\n"); | ||
178 | return NULL; /* not enough buffer */ | ||
179 | } | ||
180 | else if (w > osd->maxwidth) | ||
181 | { | ||
182 | w = osd->maxwidth; | ||
183 | } | ||
118 | } | 184 | } |
119 | #else | ||
120 | int w = LCD_BYTES2WIDTH(LCD_WIDTH2BYTES(LCD_WIDTH)); | ||
121 | int h = bufsize / LCD_WIDTH2BYTES(w); | ||
122 | 185 | ||
123 | if (h == 0) | 186 | w = _OSD_BYTES2WIDTH(_OSD_WIDTH2BYTES(w)); |
187 | osd->lcd_bitmap_stride = _OSD_BYTES2HEIGHT(_OSD_HEIGHT2BYTES(LCD_HEIGHT)); | ||
188 | osd->back_bitmap_stride = h; | ||
189 | #else /* !defined(LCD_STRIDEFORMAT) || LCD_STRIDEFORMAT != VERTICAL_STRIDE */ | ||
190 | int rowbytes = _OSD_WIDTH2BYTES(LCD_WIDTH); | ||
191 | int byterows = *bufsize / rowbytes; | ||
192 | int w = _OSD_BYTES2WIDTH(rowbytes); | ||
193 | int h = _OSD_BYTES2HEIGHT(byterows); | ||
194 | |||
195 | if (flags & OSD_INIT_MAJOR_HEIGHT) | ||
124 | { | 196 | { |
125 | DEBUGF("OSD: not enough buffer\n"); | 197 | if (h == 0 || h < osd->maxheight) |
126 | return NULL; /* not enough buffer */ | 198 | { |
199 | DEBUGF("OSD: not enough buffer\n"); | ||
200 | return NULL; | ||
201 | } | ||
202 | else if (h > osd->maxheight) | ||
203 | { | ||
204 | h = osd->maxheight; | ||
205 | } | ||
127 | } | 206 | } |
128 | #endif | 207 | else /* OSD_INIT_MAJOR_WIDTH implied */ |
208 | { | ||
209 | if (h == 0 || ((flags & OSD_INIT_MINOR_MIN) && h < osd->maxheight)) | ||
210 | { | ||
211 | DEBUGF("OSD: not enough buffer\n"); | ||
212 | return NULL; | ||
213 | } | ||
129 | 214 | ||
130 | DEBUGF("fbw:%d fbh:%d\n", w, h); | 215 | if ((flags & OSD_INIT_MINOR_MAX) && h > osd->maxheight) |
216 | h = osd->maxheight; | ||
217 | } | ||
131 | 218 | ||
132 | *width = w; | 219 | h = _OSD_BYTES2HEIGHT(_OSD_HEIGHT2BYTES(h)); |
133 | *height = h; | 220 | osd->lcd_bitmap_stride = _OSD_BYTES2WIDTH(_OSD_WIDTH2BYTES(LCD_WIDTH)); |
134 | 221 | osd->back_bitmap_stride = w; | |
135 | return (fb_data *)buf; | 222 | #endif /* end stride type selection */ |
136 | } | ||
137 | 223 | ||
138 | static inline void osd_set_vp_pos(int x, int y, int width, int height) | 224 | osd->lcd_bitmap_data = (void *)rb->lcd_framebuffer; |
139 | { | 225 | osd->back_bitmap_data = buf; |
140 | osd.vp.x = x; | 226 | |
141 | osd.vp.y = y; | 227 | osd->maxwidth = w; |
142 | osd.vp.width = width; | 228 | osd->maxheight = h; |
143 | osd.vp.height = height; | 229 | *bufsize = _OSD_BUFSIZE(w, h); |
230 | |||
231 | DEBUGF("OSD: addr(fb=%p bb=%p)\n", osd->lcd_bitmap_data, | ||
232 | osd->back_bitmap_data); | ||
233 | DEBUGF("OSD: w=%d h=%d bufsz=%lu\n", w, h, (unsigned long)*bufsize); | ||
234 | |||
235 | return buf; | ||
144 | } | 236 | } |
145 | 237 | ||
146 | /* Sync the backbuffer to the on-screen image */ | 238 | /* Set viewport coordinates */ |
147 | static void osd_lcd_update_back_buffer(void) | 239 | static void _osd_lcd_viewport_set_pos( |
240 | struct viewport *vp, int x, int y, int width, int height) | ||
148 | { | 241 | { |
149 | rb->lcd_set_framebuffer((fb_data *)osd.back_bitmap.data); | 242 | vp->x = x; |
150 | rb->lcd_bmp_part(&osd.lcd_bitmap, osd.vp.x, osd.vp.y, | 243 | vp->y = y; |
151 | 0, 0, osd.vp.width, osd.vp.height); | 244 | vp->width = width; |
152 | /* Assume it was on default framebuffer for now */ | 245 | vp->height = height; |
153 | rb->lcd_set_framebuffer(NULL); | ||
154 | } | 246 | } |
155 | 247 | ||
156 | /* Erase the OSD to restore the framebuffer */ | 248 | |
157 | static void osd_lcd_erase(void) | 249 | #if LCD_DEPTH < 4 |
250 | /** Greylib LCD routines **/ | ||
251 | |||
252 | /* Create a greylib bitmap framebuffer from a buffer */ | ||
253 | static void * _osd_grey_init_buffers(struct osd *osd, unsigned flags, | ||
254 | void *buf, size_t *bufsize) | ||
158 | { | 255 | { |
159 | rb->lcd_bmp_part(&osd.back_bitmap, 0, 0, osd.vp.x, osd.vp.y, | 256 | int w, h; |
160 | osd.vp.width, osd.vp.height); | 257 | |
258 | DEBUGF("OSD (grey): in(buf=%p bufsize=%lu)\n", buf, | ||
259 | (unsigned long)*bufsize); | ||
260 | |||
261 | grey_viewport_set_fullscreen(&osd->vp, SCREEN_MAIN); | ||
262 | |||
263 | if (flags & OSD_INIT_MAJOR_HEIGHT) | ||
264 | { | ||
265 | h = osd->maxheight; | ||
266 | w = *bufsize / h; | ||
267 | |||
268 | if (w == 0 || ((flags & OSD_INIT_MINOR_MIN) && w < osd->maxwidth)) | ||
269 | { | ||
270 | DEBUGF("OSD (grey): Not enough buffer\n"); | ||
271 | return NULL; | ||
272 | } | ||
273 | |||
274 | if ((flags & OSD_INIT_MINOR_MAX) && w > osd->maxwidth) | ||
275 | w = osd->maxwidth; | ||
276 | } | ||
277 | else /* OSD_INIT_MAJOR_WIDTH implied */ | ||
278 | { | ||
279 | w = osd->maxwidth; | ||
280 | h = *bufsize / w; | ||
281 | |||
282 | if (h == 0 || ((flags & OSD_INIT_MINOR_MIN) && h < osd->maxheight)) | ||
283 | { | ||
284 | DEBUGF("OSD (grey): Not enough buffer\n"); | ||
285 | return NULL; | ||
286 | } | ||
287 | |||
288 | if ((flags & OSD_INIT_MINOR_MAX) && h > osd->maxheight) | ||
289 | h = osd->maxheight; | ||
290 | } | ||
291 | |||
292 | /* Have to peek into _grey_info a bit */ | ||
293 | osd->lcd_bitmap_stride = _grey_info.width; | ||
294 | osd->lcd_bitmap_data = _grey_info.buffer; | ||
295 | osd->back_bitmap_stride = w; | ||
296 | osd->back_bitmap_data = buf; | ||
297 | |||
298 | osd->maxwidth = w; | ||
299 | osd->maxheight = h; | ||
300 | *bufsize = w * h; | ||
301 | |||
302 | DEBUGF("OSD (grey): addr(fb=%p bb=%p)\n", osd->lcd_bitmap_data, | ||
303 | osd->back_bitmap_data); | ||
304 | DEBUGF("OSD (grey): w=%d h=%d bufsz=%lu\n", w, h, (unsigned long)*bufsize); | ||
305 | |||
306 | return buf; | ||
161 | } | 307 | } |
308 | #endif /* LCD_DEPTH < 4*/ | ||
309 | |||
310 | |||
311 | /** Common LCD routines **/ | ||
162 | 312 | ||
163 | /* Draw the OSD image portion using the callback */ | 313 | /* Draw the OSD image portion using the callback */ |
164 | static void osd_lcd_draw_rect(int x, int y, int width, int height) | 314 | static void _osd_draw_osd_rect(struct osd *osd, int x, int y, |
315 | int width, int height) | ||
165 | { | 316 | { |
166 | rb->lcd_set_viewport(&osd.vp); | 317 | osd->lcd_set_viewport(&osd->vp); |
167 | osd.draw_cb(x, y, width, height); | 318 | osd->draw_cb(x, y, width, height); |
168 | rb->lcd_set_viewport(NULL); | 319 | osd->lcd_set_viewport(NULL); |
169 | } | 320 | } |
170 | 321 | ||
171 | /* Draw the OSD image using the callback */ | 322 | /* Draw the OSD image using the callback */ |
172 | static void osd_lcd_draw(void) | 323 | static void _osd_draw_osd(struct osd *osd) |
173 | { | 324 | { |
174 | osd_lcd_draw_rect(0, 0, osd.vp.width, osd.vp.height); | 325 | _osd_draw_osd_rect(osd, 0, 0, osd->vp.width, osd->vp.height); |
175 | } | 326 | } |
176 | 327 | ||
328 | static void _osd_update_viewport(struct osd *osd) | ||
329 | { | ||
330 | osd->lcd_update_rect(osd->vp.x, osd->vp.y, osd->vp.width, | ||
331 | osd->vp.height); | ||
332 | } | ||
177 | 333 | ||
178 | /** Public APIs **/ | 334 | /* Sync the backbuffer to the framebuffer image */ |
335 | static void _osd_update_back_buffer(struct osd *osd) | ||
336 | { | ||
337 | /* Assume it's starting with default viewport for now */ | ||
338 | osd->lcd_set_framebuffer(osd->back_bitmap_data); | ||
339 | #if LCD_DEPTH < 4 | ||
340 | if (osd->lcd_framebuffer_set_pos) | ||
341 | osd->lcd_framebuffer_set_pos(0, 0, osd->maxwidth, osd->maxheight); | ||
342 | #endif /* LCD_DEPTH < 4 */ | ||
343 | osd->lcd_bitmap_part(osd->lcd_bitmap_data, osd->vp.x, osd->vp.y, | ||
344 | osd->lcd_bitmap_stride, 0, 0, osd->vp.width, | ||
345 | osd->vp.height); | ||
346 | /* Assume it was on default framebuffer for now */ | ||
347 | osd->lcd_set_framebuffer(NULL); | ||
348 | } | ||
179 | 349 | ||
180 | /* Initialized the OSD and set its backbuffer */ | 350 | /* Erase the OSD to restore the framebuffer image */ |
181 | bool osd_init(void *backbuf, size_t backbuf_size, | 351 | static void _osd_erase_osd(struct osd *osd) |
182 | osd_draw_cb_fn_t draw_cb) | ||
183 | { | 352 | { |
184 | osd_show(OSD_HIDE); | 353 | osd->lcd_bitmap_part(osd->back_bitmap_data, 0, 0, osd->back_bitmap_stride, |
354 | osd->vp.x, osd->vp.y, osd->vp.width, osd->vp.height); | ||
355 | } | ||
185 | 356 | ||
186 | osd.status = OSD_DISABLED; /* Disabled unless all is okay */ | 357 | /* Initialized the OSD and set its backbuffer */ |
187 | osd_set_vp_pos(0, 0, 0, 0); | 358 | static bool _osd_init(struct osd *osd, unsigned flags, void *backbuf, |
188 | osd.maxwidth = osd.maxheight = 0; | 359 | size_t backbuf_size, osd_draw_cb_fn_t draw_cb, |
189 | osd.timeout = 0; | 360 | int *width, int *height, size_t *bufused) |
361 | { | ||
362 | _osd_destroy(osd); | ||
190 | 363 | ||
191 | if (!draw_cb) | 364 | if (!draw_cb) |
192 | return false; | 365 | return false; |
@@ -194,95 +367,133 @@ bool osd_init(void *backbuf, size_t backbuf_size, | |||
194 | if (!backbuf) | 367 | if (!backbuf) |
195 | return false; | 368 | return false; |
196 | 369 | ||
197 | ALIGN_BUFFER(backbuf, backbuf_size, FB_DATA_SZ); | 370 | void *backbuf_orig = backbuf; /* Save in case of ptr advance */ |
371 | ALIGN_BUFFER(backbuf, backbuf_size, MAX(FB_DATA_SZ, 4)); | ||
198 | 372 | ||
199 | if (!backbuf_size) | 373 | if (!backbuf_size) |
200 | return false; | 374 | return false; |
201 | 375 | ||
202 | rb->viewport_set_fullscreen(&osd.vp, SCREEN_MAIN); | 376 | if (flags & OSD_INIT_MAJOR_HEIGHT) |
377 | { | ||
378 | if (!height || *height <= 0) | ||
379 | return false; | ||
203 | 380 | ||
204 | fb_data *backfb = buf_to_fb_bitmap(backbuf, backbuf_size, | 381 | if ((flags & (OSD_INIT_MINOR_MIN | OSD_INIT_MINOR_MAX)) && |
205 | &osd.maxwidth, &osd.maxheight); | 382 | (!width || *width <= 0)) |
383 | { | ||
384 | return false; | ||
385 | } | ||
386 | } | ||
387 | else | ||
388 | { | ||
389 | if (!width || *width <= 0) | ||
390 | return false; | ||
391 | |||
392 | if ((flags & (OSD_INIT_MINOR_MIN | OSD_INIT_MINOR_MAX)) && | ||
393 | (!height || *height <= 0)) | ||
394 | { | ||
395 | return false; | ||
396 | } | ||
397 | } | ||
398 | |||
399 | /* Store requested sizes in max(width|height) */ | ||
400 | if (width) | ||
401 | osd->maxwidth = *width; | ||
402 | else | ||
403 | osd->maxwidth = LCD_WIDTH; | ||
206 | 404 | ||
207 | if (!backfb) | 405 | if (height) |
406 | osd->maxheight = *height; | ||
407 | else | ||
408 | osd->maxheight = LCD_HEIGHT; | ||
409 | |||
410 | if (!osd->init_buffers(osd, flags, backbuf, &backbuf_size)) | ||
411 | { | ||
412 | osd->maxwidth = osd->maxheight = 0; | ||
208 | return false; | 413 | return false; |
414 | } | ||
209 | 415 | ||
210 | osd.draw_cb = draw_cb; | 416 | osd->draw_cb = draw_cb; |
211 | 417 | ||
212 | /* LCD framebuffer bitmap */ | 418 | if (bufused) |
213 | osd.lcd_bitmap.width = LCD_BYTES2WIDTH(LCD_WIDTH2BYTES(LCD_WIDTH)); | 419 | *bufused = backbuf_size + (backbuf_orig - backbuf); |
214 | osd.lcd_bitmap.height = LCD_BYTES2HEIGHT(LCD_HEIGHT2BYTES(LCD_HEIGHT)); | ||
215 | #if LCD_DEPTH > 1 | ||
216 | osd.lcd_bitmap.format = FORMAT_NATIVE; | ||
217 | osd.lcd_bitmap.maskdata = NULL; | ||
218 | #endif | ||
219 | #ifdef HAVE_LCD_COLOR | ||
220 | osd.lcd_bitmap.alpha_offset = 0; | ||
221 | #endif | ||
222 | osd.lcd_bitmap.data = (void *)rb->lcd_framebuffer; | ||
223 | |||
224 | /* Backbuffer bitmap */ | ||
225 | osd.back_bitmap.width = osd.maxwidth; | ||
226 | osd.back_bitmap.height = osd.maxheight; | ||
227 | #if LCD_DEPTH > 1 | ||
228 | osd.back_bitmap.format = FORMAT_NATIVE; | ||
229 | osd.back_bitmap.maskdata = NULL; | ||
230 | #endif | ||
231 | #ifdef HAVE_LCD_COLOR | ||
232 | osd.back_bitmap.alpha_offset = 0; | ||
233 | #endif | ||
234 | osd.back_bitmap.data = (void *)backfb; | ||
235 | 420 | ||
236 | DEBUGF("FB:%p BB:%p\n", osd.lcd_bitmap.data, osd.back_bitmap.data); | 421 | if (width) |
422 | *width = osd->maxwidth; | ||
423 | |||
424 | if (height) | ||
425 | *height = osd->maxheight; | ||
237 | 426 | ||
238 | /* Set the default position to the whole thing */ | 427 | /* Set the default position to the whole thing */ |
239 | osd_set_vp_pos(0, 0, osd.maxwidth, osd.maxheight); | 428 | osd->set_viewport_pos(&osd->vp, 0, 0, osd->maxwidth, osd->maxheight); |
429 | |||
430 | osd->status = OSD_HIDDEN; /* Ready when you are */ | ||
240 | 431 | ||
241 | osd.status = OSD_HIDDEN; /* Ready when you are */ | 432 | return true; |
433 | } | ||
434 | |||
435 | static void _osd_destroy(struct osd *osd) | ||
436 | { | ||
437 | _osd_show(osd, OSD_HIDE); | ||
438 | |||
439 | /* Set to essential defaults */ | ||
440 | osd->status = OSD_DISABLED; | ||
441 | osd->set_viewport_pos(&osd->vp, 0, 0, 0, 0); | ||
442 | osd->maxwidth = osd->maxheight = 0; | ||
443 | osd->timeout = 0; | ||
444 | } | ||
445 | |||
446 | /* Redraw the entire OSD */ | ||
447 | static bool _osd_update(struct osd *osd) | ||
448 | { | ||
449 | if (osd->status != OSD_VISIBLE) | ||
450 | return false; | ||
451 | |||
452 | _osd_draw_osd(osd); | ||
453 | _osd_update_viewport(osd); | ||
242 | return true; | 454 | return true; |
243 | } | 455 | } |
244 | 456 | ||
245 | /* Show/Hide the OSD on screen */ | 457 | /* Show/Hide the OSD on screen */ |
246 | bool osd_show(unsigned flags) | 458 | static bool _osd_show(struct osd *osd, unsigned flags) |
247 | { | 459 | { |
248 | if (flags & OSD_SHOW) | 460 | if (flags & OSD_SHOW) |
249 | { | 461 | { |
250 | switch (osd.status) | 462 | switch (osd->status) |
251 | { | 463 | { |
252 | case OSD_DISABLED: | 464 | case OSD_DISABLED: |
253 | break; /* No change */ | 465 | break; /* No change */ |
254 | 466 | ||
255 | case OSD_HIDDEN: | 467 | case OSD_HIDDEN: |
256 | osd_lcd_update_back_buffer(); | 468 | _osd_update_back_buffer(osd); |
257 | osd.status = OSD_VISIBLE; | 469 | osd->status = OSD_VISIBLE; |
258 | osd_update(); | 470 | _osd_update(osd); |
259 | osd.hide_tick = *rb->current_tick + osd.timeout; | 471 | osd->hide_tick = *rb->current_tick + osd->timeout; |
260 | break; | 472 | break; |
261 | 473 | ||
262 | case OSD_VISIBLE: | 474 | case OSD_VISIBLE: |
263 | if (flags & OSD_UPDATENOW) | 475 | if (flags & OSD_UPDATENOW) |
264 | osd_update(); | 476 | _osd_update(osd); |
265 | /* Fall-through */ | 477 | /* Fall-through */ |
266 | case OSD_ERASED: | 478 | case OSD_ERASED: |
267 | osd.hide_tick = *rb->current_tick + osd.timeout; | 479 | osd->hide_tick = *rb->current_tick + osd->timeout; |
268 | return true; | 480 | return true; |
269 | } | 481 | } |
270 | } | 482 | } |
271 | else | 483 | else |
272 | { | 484 | { |
273 | switch (osd.status) | 485 | switch (osd->status) |
274 | { | 486 | { |
275 | case OSD_DISABLED: | 487 | case OSD_DISABLED: |
276 | case OSD_HIDDEN: | 488 | case OSD_HIDDEN: |
277 | break; | 489 | break; |
278 | 490 | ||
279 | case OSD_VISIBLE: | 491 | case OSD_VISIBLE: |
280 | osd_lcd_erase(); | 492 | _osd_erase_osd(osd); |
281 | rb->lcd_update_rect(osd.vp.x, osd.vp.y, osd.vp.width, | 493 | _osd_update_viewport(osd); |
282 | osd.vp.height); | ||
283 | /* Fall-through */ | 494 | /* Fall-through */ |
284 | case OSD_ERASED: | 495 | case OSD_ERASED: |
285 | osd.status = OSD_HIDDEN; | 496 | osd->status = OSD_HIDDEN; |
286 | return true; | 497 | return true; |
287 | } | 498 | } |
288 | } | 499 | } |
@@ -290,30 +501,20 @@ bool osd_show(unsigned flags) | |||
290 | return false; | 501 | return false; |
291 | } | 502 | } |
292 | 503 | ||
293 | /* Redraw the entire OSD */ | ||
294 | bool osd_update(void) | ||
295 | { | ||
296 | if (osd.status != OSD_VISIBLE) | ||
297 | return false; | ||
298 | |||
299 | osd_lcd_draw(); | ||
300 | |||
301 | rb->lcd_update_rect(osd.vp.x, osd.vp.y, osd.vp.width, | ||
302 | osd.vp.height); | ||
303 | |||
304 | return true; | ||
305 | } | ||
306 | |||
307 | /* Redraw part of the OSD (viewport-relative coordinates) */ | 504 | /* Redraw part of the OSD (viewport-relative coordinates) */ |
308 | bool osd_update_rect(int x, int y, int width, int height) | 505 | static bool _osd_update_rect(struct osd *osd, int x, int y, int width, |
506 | int height) | ||
309 | { | 507 | { |
310 | if (osd.status != OSD_VISIBLE) | 508 | if (osd->status != OSD_VISIBLE) |
311 | return false; | 509 | return false; |
312 | 510 | ||
313 | osd_lcd_draw_rect(x, y, width, height); | 511 | _osd_draw_osd_rect(osd, x, y, width, height); |
314 | 512 | ||
315 | if (x + width > osd.vp.width) | 513 | int vp_x = osd->vp.x; |
316 | width = osd.vp.width - x; | 514 | int vp_w = osd->vp.width; |
515 | |||
516 | if (x + width > vp_w) | ||
517 | width = vp_w - x; | ||
317 | 518 | ||
318 | if (x < 0) | 519 | if (x < 0) |
319 | { | 520 | { |
@@ -324,8 +525,11 @@ bool osd_update_rect(int x, int y, int width, int height) | |||
324 | if (width <= 0) | 525 | if (width <= 0) |
325 | return false; | 526 | return false; |
326 | 527 | ||
327 | if (y + height > osd.vp.height) | 528 | int vp_y = osd->vp.y; |
328 | height = osd.vp.height - y; | 529 | int vp_h = osd->vp.height; |
530 | |||
531 | if (y + height > vp_h) | ||
532 | height = vp_h - y; | ||
329 | 533 | ||
330 | if (y < 0) | 534 | if (y < 0) |
331 | { | 535 | { |
@@ -336,135 +540,313 @@ bool osd_update_rect(int x, int y, int width, int height) | |||
336 | if (height <= 0) | 540 | if (height <= 0) |
337 | return false; | 541 | return false; |
338 | 542 | ||
339 | rb->lcd_update_rect(osd.vp.x + x, osd.vp.y + y, width, height); | 543 | osd->lcd_update_rect(vp_x + x, vp_y + y, width, height); |
340 | 544 | ||
341 | return true; | 545 | return true; |
342 | } | 546 | } |
343 | 547 | ||
344 | /* Set a new screen location and size (screen coordinates) */ | 548 | /* Set a new screen location and size (screen coordinates) */ |
345 | bool osd_update_pos(int x, int y, int width, int height) | 549 | static bool _osd_update_pos(struct osd *osd, int x, int y, int width, |
550 | int height) | ||
346 | { | 551 | { |
347 | if (osd.status == OSD_DISABLED) | 552 | if (osd->status == OSD_DISABLED) |
348 | return false; | 553 | return false; |
349 | 554 | ||
350 | if (width < 0) | 555 | if (width < 0) |
351 | width = 0; | 556 | width = 0; |
352 | else if (width > osd.maxwidth) | 557 | else if (width > osd->maxwidth) |
353 | width = osd.maxwidth; | 558 | width = osd->maxwidth; |
354 | 559 | ||
355 | if (height < 0) | 560 | if (height < 0) |
356 | height = 0; | 561 | height = 0; |
357 | else if (height > osd.maxheight) | 562 | else if (height > osd->maxheight) |
358 | height = osd.maxheight; | 563 | height = osd->maxheight; |
564 | |||
565 | int vp_x = osd->vp.x; | ||
566 | int vp_y = osd->vp.y; | ||
567 | int vp_w = osd->vp.width; | ||
568 | int vp_h = osd->vp.height; | ||
359 | 569 | ||
360 | if (x == osd.vp.x && y == osd.vp.y && | 570 | if (x == vp_x && y == vp_y && width == vp_w && height == vp_h) |
361 | width == osd.vp.width && height == osd.vp.height) | ||
362 | return false; /* No change */ | 571 | return false; /* No change */ |
363 | 572 | ||
364 | if (osd.status != OSD_VISIBLE) | 573 | if (osd->status != OSD_VISIBLE) |
365 | { | 574 | { |
366 | /* Not visible - just update pos */ | 575 | /* Not visible - just update pos */ |
367 | osd_set_vp_pos(x, y, width, height); | 576 | osd->set_viewport_pos(&osd->vp, x, y, width, height); |
368 | return false; | 577 | return false; |
369 | } | 578 | } |
370 | 579 | ||
371 | /* Visible area has changed */ | 580 | /* Visible area has changed */ |
372 | osd_lcd_erase(); | 581 | _osd_erase_osd(osd); |
373 | 582 | ||
374 | /* Update the smallest rectangle that encloses both the old and new | 583 | /* Update the smallest rectangle that encloses both the old and new |
375 | regions to make the change free of flicker (they may overlap) */ | 584 | regions to make the change free of flicker (they may overlap) */ |
376 | int xu = MIN(osd.vp.x, x); | 585 | int xu = MIN(vp_x, x); |
377 | int yu = MIN(osd.vp.y, y); | 586 | int yu = MIN(vp_y, y); |
378 | int wu = MAX(osd.vp.x + osd.vp.width, x + width) - xu; | 587 | int wu = MAX(vp_x + vp_w, x + width) - xu; |
379 | int hu = MAX(osd.vp.y + osd.vp.height, y + height) - yu; | 588 | int hu = MAX(vp_y + vp_h, y + height) - yu; |
380 | 589 | ||
381 | osd_set_vp_pos(x, y, width, height); | 590 | osd->set_viewport_pos(&osd->vp, x, y, width, height); |
382 | osd_lcd_update_back_buffer(); | 591 | _osd_update_back_buffer(osd); |
383 | osd_lcd_draw(); | 592 | _osd_draw_osd(osd); |
593 | osd->lcd_update_rect(xu, yu, wu, hu); | ||
384 | 594 | ||
385 | rb->lcd_update_rect(xu, yu, wu, hu); | ||
386 | return true; | 595 | return true; |
387 | } | 596 | } |
388 | 597 | ||
389 | /* Call periodically to have the OSD timeout and hide itself */ | 598 | /* Call periodically to have the OSD timeout and hide itself */ |
390 | void osd_monitor_timeout(void) | 599 | static void _osd_monitor_timeout(struct osd *osd) |
391 | { | 600 | { |
392 | if (osd.status <= OSD_HIDDEN) | 601 | if (osd->status <= OSD_HIDDEN) |
393 | return; /* Already hidden/disabled */ | 602 | return; /* Already hidden/disabled */ |
394 | 603 | ||
395 | if (osd.timeout > 0 && TIME_AFTER(*rb->current_tick, osd.hide_tick)) | 604 | if (osd->timeout > 0 && TIME_AFTER(*rb->current_tick, osd->hide_tick)) |
396 | osd_show(OSD_HIDE); | 605 | _osd_show(osd, OSD_HIDE); |
397 | } | 606 | } |
398 | 607 | ||
399 | /* Set the OSD timeout value. <= 0 = never timeout */ | 608 | /* Set the OSD timeout value. <= 0 = never timeout */ |
400 | void osd_set_timeout(long timeout) | 609 | static void _osd_set_timeout(struct osd *osd, long timeout) |
401 | { | 610 | { |
402 | if (osd.status == OSD_DISABLED) | 611 | if (osd->status == OSD_DISABLED) |
403 | return; | 612 | return; |
404 | 613 | ||
405 | osd.timeout = timeout; | 614 | osd->timeout = timeout; |
406 | osd_monitor_timeout(); | 615 | _osd_monitor_timeout(osd); |
407 | } | 616 | } |
408 | 617 | ||
409 | /* Use the OSD viewport context */ | 618 | /* Use the OSD viewport context */ |
410 | struct viewport * osd_get_viewport(void) | 619 | static inline struct viewport * _osd_get_viewport(struct osd *osd) |
411 | { | 620 | { |
412 | return &osd.vp; | 621 | return &osd->vp; |
413 | } | 622 | } |
414 | 623 | ||
415 | /* Get the maximum dimensions calculated by osd_init() */ | 624 | /* Get the maximum dimensions calculated by osd_init() */ |
416 | void osd_get_max_dims(int *maxwidth, int *maxheight) | 625 | static void _osd_get_max_dims(struct osd *osd, |
626 | int *maxwidth, int *maxheight) | ||
417 | { | 627 | { |
418 | if (maxwidth) | 628 | if (maxwidth) |
419 | *maxwidth = osd.maxwidth; | 629 | *maxwidth = osd->maxwidth; |
420 | 630 | ||
421 | if (maxheight) | 631 | if (maxheight) |
422 | *maxheight = osd.maxheight; | 632 | *maxheight = osd->maxheight; |
423 | } | 633 | } |
424 | 634 | ||
425 | /* Is the OSD enabled? */ | 635 | /* Is the OSD enabled? */ |
426 | bool osd_enabled(void) | 636 | static inline bool _osd_enabled(struct osd *osd) |
427 | { | 637 | { |
428 | return osd.status != OSD_DISABLED; | 638 | return osd->status != OSD_DISABLED; |
429 | } | 639 | } |
430 | 640 | ||
431 | 641 | ||
432 | /** LCD update substitutes **/ | 642 | /** LCD update substitutes **/ |
433 | 643 | ||
434 | /* Prepare LCD framebuffer for regular drawing */ | 644 | /* Prepare LCD framebuffer for regular drawing */ |
435 | void osd_lcd_update_prepare(void) | 645 | static inline void _osd_lcd_update_prepare(struct osd *osd) |
436 | { | 646 | { |
437 | if (osd.status == OSD_VISIBLE) | 647 | if (osd->status == OSD_VISIBLE) |
438 | { | 648 | { |
439 | osd.status = OSD_ERASED; | 649 | osd->status = OSD_ERASED; |
440 | osd_lcd_erase(); | 650 | _osd_erase_osd(osd); |
441 | } | 651 | } |
442 | } | 652 | } |
443 | 653 | ||
444 | /* Update the whole screen */ | 654 | /* Update the whole screen */ |
445 | void osd_lcd_update(void) | 655 | static inline void _osd_lcd_update(struct osd *osd) |
446 | { | 656 | { |
447 | if (osd.status == OSD_ERASED) | 657 | if (osd->status == OSD_ERASED) |
448 | { | 658 | { |
449 | /* Save the screen image underneath and restore the OSD image */ | 659 | /* Save the screen image underneath and restore the OSD image */ |
450 | osd.status = OSD_VISIBLE; | 660 | osd->status = OSD_VISIBLE; |
451 | osd_lcd_update_back_buffer(); | 661 | _osd_update_back_buffer(osd); |
452 | osd_lcd_draw(); | 662 | _osd_draw_osd(osd); |
453 | } | 663 | } |
454 | 664 | ||
455 | rb->lcd_update(); | 665 | osd->lcd_update(); |
456 | } | 666 | } |
457 | 667 | ||
458 | /* Update a part of the screen */ | 668 | /* Update a part of the screen */ |
459 | void osd_lcd_update_rect(int x, int y, int width, int height) | 669 | static void _osd_lcd_update_rect(struct osd *osd, |
670 | int x, int y, int width, int height) | ||
460 | { | 671 | { |
461 | if (osd.status == OSD_ERASED) | 672 | if (osd->status == OSD_ERASED) |
462 | { | 673 | { |
463 | /* Save the screen image underneath and restore the OSD image */ | 674 | /* Save the screen image underneath and restore the OSD image */ |
464 | osd.status = OSD_VISIBLE; | 675 | osd->status = OSD_VISIBLE; |
465 | osd_lcd_update_back_buffer(); | 676 | _osd_update_back_buffer(osd); |
466 | osd_lcd_draw(); | 677 | _osd_draw_osd(osd); |
467 | } | 678 | } |
468 | 679 | ||
469 | rb->lcd_update_rect(x, y, width, height); | 680 | osd->lcd_update_rect(x, y, width, height); |
681 | } | ||
682 | |||
683 | /* Native LCD, public */ | ||
684 | bool osd_init(unsigned flags, void *backbuf, size_t backbuf_size, | ||
685 | osd_draw_cb_fn_t draw_cb, int *width, int *height, | ||
686 | size_t *bufused) | ||
687 | { | ||
688 | native_osd.init_buffers = _osd_lcd_init_buffers; | ||
689 | native_osd.set_viewport_pos = _osd_lcd_viewport_set_pos; | ||
690 | native_osd.lcd_update = rb->lcd_update; | ||
691 | native_osd.lcd_update_rect = rb->lcd_update_rect; | ||
692 | native_osd.lcd_set_viewport = rb->lcd_set_viewport; | ||
693 | native_osd.lcd_set_framebuffer = (void *)rb->lcd_set_framebuffer; | ||
694 | #if LCD_DEPTH < 4 | ||
695 | native_osd.lcd_framebuffer_set_pos = NULL; | ||
696 | #endif /* LCD_DEPTH < 4 */ | ||
697 | native_osd.lcd_bitmap_part = (void *)rb->lcd_bitmap_part; | ||
698 | |||
699 | return _osd_init(&native_osd, flags, backbuf, backbuf_size, draw_cb, | ||
700 | width, height, bufused); | ||
701 | } | ||
702 | |||
703 | void osd_destroy(void) | ||
704 | { | ||
705 | return _osd_destroy(&native_osd); | ||
706 | } | ||
707 | |||
708 | bool osd_show(unsigned flags) | ||
709 | { | ||
710 | return _osd_show(&native_osd, flags); | ||
711 | } | ||
712 | |||
713 | bool osd_update(void) | ||
714 | { | ||
715 | return _osd_update(&native_osd); | ||
716 | } | ||
717 | |||
718 | bool osd_update_rect(int x, int y, int width, int height) | ||
719 | { | ||
720 | return _osd_update_rect(&native_osd, x, y, width, height); | ||
721 | } | ||
722 | |||
723 | bool osd_update_pos(int x, int y, int width, int height) | ||
724 | { | ||
725 | return _osd_update_pos(&native_osd, x, y, width, height); | ||
726 | } | ||
727 | |||
728 | void osd_monitor_timeout(void) | ||
729 | { | ||
730 | _osd_monitor_timeout(&native_osd); | ||
731 | } | ||
732 | |||
733 | void osd_set_timeout(long timeout) | ||
734 | { | ||
735 | _osd_set_timeout(&native_osd, timeout); | ||
736 | } | ||
737 | |||
738 | struct viewport * osd_get_viewport(void) | ||
739 | { | ||
740 | return _osd_get_viewport(&native_osd); | ||
741 | } | ||
742 | |||
743 | void osd_get_max_dims(int *maxwidth, int *maxheight) | ||
744 | { | ||
745 | _osd_get_max_dims(&native_osd, maxwidth, maxheight); | ||
746 | } | ||
747 | |||
748 | bool osd_enabled(void) | ||
749 | { | ||
750 | return _osd_enabled(&native_osd); | ||
751 | } | ||
752 | |||
753 | void osd_lcd_update_prepare(void) | ||
754 | { | ||
755 | _osd_lcd_update_prepare(&native_osd); | ||
756 | } | ||
757 | |||
758 | |||
759 | void osd_lcd_update(void) | ||
760 | { | ||
761 | _osd_lcd_update(&native_osd); | ||
762 | } | ||
763 | |||
764 | void osd_lcd_update_rect(int x, int y, int width, int height) | ||
765 | { | ||
766 | _osd_lcd_update_rect(&native_osd, x, y, width, height); | ||
767 | } | ||
768 | |||
769 | #if LCD_DEPTH < 4 | ||
770 | /* Greylib LCD, public */ | ||
771 | bool osd_grey_init(unsigned flags, void *backbuf, size_t backbuf_size, | ||
772 | osd_draw_cb_fn_t draw_cb, int *width, int *height, | ||
773 | size_t *bufused) | ||
774 | { | ||
775 | grey_osd.init_buffers = _osd_grey_init_buffers; | ||
776 | grey_osd.set_viewport_pos = grey_viewport_set_pos; | ||
777 | grey_osd.lcd_update = grey_update; | ||
778 | grey_osd.lcd_update_rect = grey_update_rect; | ||
779 | grey_osd.lcd_set_viewport = grey_set_viewport; | ||
780 | grey_osd.lcd_set_framebuffer = (void *)grey_set_framebuffer; | ||
781 | grey_osd.lcd_framebuffer_set_pos = grey_framebuffer_set_pos; | ||
782 | grey_osd.lcd_bitmap_part = (void *)grey_gray_bitmap_part; | ||
783 | |||
784 | return _osd_init(&grey_osd, flags, backbuf, backbuf_size, draw_cb, | ||
785 | width, height, bufused); | ||
786 | } | ||
787 | |||
788 | void osd_grey_destroy(void) | ||
789 | { | ||
790 | return _osd_destroy(&grey_osd); | ||
791 | } | ||
792 | |||
793 | bool osd_grey_show(unsigned flags) | ||
794 | { | ||
795 | return _osd_show(&grey_osd, flags); | ||
796 | } | ||
797 | |||
798 | bool osd_grey_update(void) | ||
799 | { | ||
800 | return _osd_update(&grey_osd); | ||
801 | } | ||
802 | |||
803 | bool osd_grey_update_rect(int x, int y, int width, int height) | ||
804 | { | ||
805 | return _osd_update_rect(&grey_osd, x, y, width, height); | ||
806 | } | ||
807 | |||
808 | bool osd_grey_update_pos(int x, int y, int width, int height) | ||
809 | { | ||
810 | return _osd_update_pos(&grey_osd, x, y, width, height); | ||
811 | } | ||
812 | |||
813 | void osd_grey_monitor_timeout(void) | ||
814 | { | ||
815 | _osd_monitor_timeout(&grey_osd); | ||
816 | } | ||
817 | |||
818 | void osd_grey_set_timeout(long timeout) | ||
819 | { | ||
820 | _osd_set_timeout(&grey_osd, timeout); | ||
821 | } | ||
822 | |||
823 | struct viewport * osd_grey_get_viewport(void) | ||
824 | { | ||
825 | return _osd_get_viewport(&grey_osd); | ||
826 | } | ||
827 | |||
828 | void osd_grey_get_max_dims(int *maxwidth, int *maxheight) | ||
829 | { | ||
830 | _osd_get_max_dims(&grey_osd, maxwidth, maxheight); | ||
831 | } | ||
832 | |||
833 | bool osd_grey_enabled(void) | ||
834 | { | ||
835 | return _osd_enabled(&grey_osd); | ||
836 | } | ||
837 | |||
838 | void osd_grey_lcd_update_prepare(void) | ||
839 | { | ||
840 | _osd_lcd_update_prepare(&grey_osd); | ||
841 | } | ||
842 | |||
843 | void osd_grey_lcd_update(void) | ||
844 | { | ||
845 | _osd_lcd_update(&grey_osd); | ||
846 | } | ||
847 | |||
848 | void osd_grey_lcd_update_rect(int x, int y, int width, int height) | ||
849 | { | ||
850 | _osd_lcd_update_rect(&grey_osd, x, y, width, height); | ||
470 | } | 851 | } |
852 | #endif /* LCD_DEPTH < 4 */ | ||