add input, basic config
[sdl_omap.git] / src / video / omapdss / main.c
CommitLineData
0ec348b9 1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
3cb98c5e 4#include <strings.h>
5#include <ctype.h>
0ec348b9 6#include <sys/time.h>
7#include <SDL/SDL.h>
8
9#include "pmsdl.h"
3cb98c5e 10#include "common/input.h"
0ec348b9 11#include "linux/fbdev.h"
3cb98c5e 12#include "linux/oshide.h"
0ec348b9 13
14static SDL_Surface *g_screen;
15static void *g_screen_fbp;
16static Uint16 g_8bpp_pal[256];
17static Uint32 g_start_ticks;
0ec348b9 18
19static inline int min(int v1, int v2)
20{
21 return v1 < v2 ? v1 : v2;
22}
23
0ec348b9 24static SDL_Surface *alloc_surface(int w, int h, int bpp)
25{
26 // SDL has some pointer overuse, every surface has a format,
27 // why make format accessible through pointer?
28 struct {
29 SDL_Surface s;
30 SDL_PixelFormat f;
31 } *ret;
32
33 ret = calloc(1, sizeof(*ret));
34 if (ret == NULL)
35 return NULL;
36
37 ret->s.format = &ret->f;
38 ret->f.BitsPerPixel = bpp;
39 ret->f.BytesPerPixel = (bpp + 7) / 8;
40
41 ret->s.w = w;
42 ret->s.h = h;
43 ret->s.pitch = w * ret->f.BytesPerPixel;
44 // XXX: more fields
45
46 return &ret->s;
47}
48
3cb98c5e 49static char *sskip(char *p)
50{
51 while (*p && isspace(*p))
52 p++;
53 return p;
54}
55
56static char *nsskip(char *p)
57{
58 while (*p && !isspace(*p))
59 p++;
60 return p;
61}
62
63static int check_token(const char *p, const char *token)
64{
65 int tlen = strlen(token);
66 return strncasecmp(p, token, tlen) == 0 && isspace(p[tlen]);
67}
68
69static void do_config(void)
70{
71 char buff[256];
72 FILE *f;
73
74 f = fopen("pmsdl.cfg", "r");
75 if (f == NULL)
76 return;
77
78 while (!feof(f)) {
79 char *p, *line = fgets(buff, sizeof(buff), f);
80 if (line == NULL)
81 break;
82 p = line = sskip(line);
83 if (*p == '#')
84 continue;
85
86 if (check_token(p, "bind")) {
87 char *key, *key_end, *sdlkey, *sdlkey_end;
88 key = sskip(p + 5);
89 key_end = nsskip(key);
90 p = sskip(key_end);
91 if (*p != '=')
92 goto bad;
93 sdlkey = sskip(p + 1);
94 sdlkey_end = nsskip(sdlkey);
95 p = sskip(sdlkey_end);
96 if (*key == 0 || *sdlkey == 0 || *p != 0)
97 goto bad;
98 *key_end = *sdlkey_end = 0;
99
100 pmsdl_input_bind(key, sdlkey);
101 continue;
102 }
103
104bad:
105 err("config: failed to parse: %s", line);
106 }
107 fclose(f);
108}
109
0ec348b9 110DECLSPEC int SDLCALL
111SDL_Init(Uint32 flags)
112{
113 trace("%08x", flags);
114
3cb98c5e 115 if (g_start_ticks == 0) {
116 pmsdl_input_init();
117 oshide_init();
118 do_config();
119 }
120
0ec348b9 121 g_start_ticks = 0;
122 g_start_ticks = SDL_GetTicks();
123
124 return 0;
125}
126
127DECLSPEC void SDLCALL
128SDL_Quit(void)
129{
130 trace("");
3cb98c5e 131
132 if (g_start_ticks != 0) {
133 oshide_finish();
134 g_start_ticks = 0;
135 }
0ec348b9 136}
137
138DECLSPEC int SDLCALL
139SDL_InitSubSystem(Uint32 flags)
140{
141 trace("%08x", flags);
142 return 0;
143}
144
145DECLSPEC void SDLCALL
146SDL_QuitSubSystem(Uint32 flags)
147{
148 trace("%08x", flags);
149}
150
151DECLSPEC Uint32 SDLCALL
152SDL_GetTicks(void)
153{
154 struct timeval tv;
155 Uint32 ret;
156
157 gettimeofday(&tv, NULL);
158 ret = tv.tv_sec * 1000;
159 ret += tv.tv_usec * 1048 >> 20;
160
161 ret -= g_start_ticks;
162 dbg(" SDL_GetTicks %d", ret);
163 return ret;
164}
165
166DECLSPEC SDL_Surface * SDLCALL
167SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags)
168{
169 struct vout_fbdev *fbdev;
170
171 trace("%d, %d, %d, %08x", width, height, bpp, flags);
172
3cb98c5e 173 if (bpp == 0)
174 bpp = 16;
175
0ec348b9 176 if (bpp != 8 && bpp != 16) {
177 err("unsupported bpp: %d\n", bpp);
178 return NULL;
179 }
180
181 // XXX: destroy old g_screen?
182
183 g_screen = alloc_surface(width, height, bpp);
184 if (g_screen == NULL)
185 return NULL;
186
187 fbdev = vout_fbdev_init("/dev/fb0", &width, &height, 0);
188 if (fbdev == NULL)
189 goto fail_fbdev_init;
190
191 g_screen_fbp = vout_fbdev_flip(fbdev);
192 if (bpp == 16)
193 g_screen->pixels = g_screen_fbp;
194 else
195 // we have to fake this for now..
196 g_screen->pixels = calloc(g_screen->pitch * height, 1);
197
198 if (g_screen->pixels == NULL) {
199 err("fb NULL");
200 goto fail_pixels;
201 }
202 g_screen->hwdata = (void *)fbdev;
203
204 dbg("returning %p", g_screen);
205 return g_screen;
206
207fail_pixels:
208 vout_fbdev_finish(fbdev);
209fail_fbdev_init:
210 free(g_screen);
211 g_screen = NULL;
212 return NULL;
213}
214
215DECLSPEC int SDLCALL
216SDL_Flip(SDL_Surface *screen)
217{
218 struct vout_fbdev *fbdev;
219
220 trace("%p", screen);
221
222 if (screen != g_screen) {
223 err("flip not on screen surface?");
224 return -1;
225 }
226
227 if (screen->format->BitsPerPixel == 8) {
228 int l = screen->pitch * screen->h;
3cb98c5e 229#ifdef __arm__
0ec348b9 230 do_clut(g_screen_fbp, screen->pixels, g_8bpp_pal, l);
231#else
232 Uint16 *d = g_screen_fbp;
233 Uint8 *s = screen->pixels;
234
235 // XXX: perhaps optimize this sh*t
236 for (; l > 0; d++, s++, l--)
237 *d = g_8bpp_pal[*s];
238#endif
239 }
240
241 fbdev = (void *)screen->hwdata;
242 g_screen_fbp = vout_fbdev_flip(fbdev);
243
244 if (screen->format->BitsPerPixel != 8)
245 screen->pixels = g_screen_fbp;
246
247 return 0;
248}
249
250static int do_rect_clip(const SDL_Surface *s, SDL_Rect *r)
251{
252 int x = r->x, y = r->y, w = r->w, h = r->h;
253
254 if (x < 0) {
255 w += x;
256 if (w < 0)
257 w = 0;
258 x = 0;
259 }
260 if (y < 0) {
261 h += y;
262 if (h < 0)
263 h = 0;
264 y = 0;
265 }
266 if (x + w > s->w) {
267 w = s->w - x;
268 if (w < 0)
269 w = 0;
270 }
271 if (y + h > s->h) {
272 h = s->h - y;
273 if (h < 0)
274 h = 0;
275 }
276
277 r->x = x; r->y = y; r->w = w; r->h = h;
278 return (w > 0 && h > 0) ? 0 : -1;
279}
280
281DECLSPEC int SDLCALL
282SDL_UpperBlit(SDL_Surface *src, SDL_Rect *srcrect,
283 SDL_Surface *dst, SDL_Rect *dstrect)
284{
285 int sx = 0, sy = 0, sw, sh;
286 int dx = 0, dy = 0;
287 SDL_Rect tmprect = { 0, };
288
289 trace("%p, %p, %p, %p", src, srcrect, dst, dstrect);
290
291 if (src == NULL || dst == NULL)
292 return -1;
293
294 if (srcrect != NULL) {
295 // XXX: dst pos may need to be adjusted in some corner cases
296 if (do_rect_clip(src, srcrect) < 0)
297 return -1;
298 sx = srcrect->x;
299 sy = srcrect->y;
300 sw = srcrect->w;
301 sh = srcrect->h;
302 } else {
303 sw = src->w;
304 sh = src->h;
305 }
306
307 if (dstrect == NULL)
308 dstrect = &tmprect;
309
310 // SDL just uses source w and h
311 dstrect->w = sw;
312 dstrect->h = sh;
313 if (do_rect_clip(dst, dstrect) < 0)
314 return -1;
315 dx = dstrect->x;
316 dy = dstrect->y;
317 sw = dstrect->w;
318 sh = dstrect->h;
319
320 dbg("(%d %d %d %d) -> (%d %d %d %d)", sx, sy, sw, sh, dx, dy, sw, sh);
321
322 if (src->format->BitsPerPixel == dst->format->BitsPerPixel) {
323 int Bpp = src->format->BytesPerPixel;
324 int dpitch = dst->pitch;
325 int spitch = src->pitch;
326 Uint8 *d = (Uint8 *)dst->pixels + dpitch * dy + dx * Bpp;
327 Uint8 *s = (Uint8 *)src->pixels + spitch * sy + sx * Bpp;
328
329 for (sw *= Bpp; sh > 0; d += dpitch, s += spitch, sh--)
330 memcpy(d, s, sw);
331 }
3cb98c5e 332 else
333 not_supported();
0ec348b9 334
335 return 0;
336}
337
338DECLSPEC SDL_Surface * SDLCALL
339SDL_CreateRGBSurface(Uint32 flags, int width, int height, int depth,
340 Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
341{
342 SDL_Surface *ret;
343
344 trace("%08x, %d, %d, %d, %04x, %04x, %04x, %04x",
345 flags, width, height, depth, Rmask, Gmask, Bmask, Amask);
346
347 ret = alloc_surface(width, height, depth);
348 if (ret == NULL)
349 return NULL;
350
351 ret->pixels = calloc(ret->pitch * height, 1);
352 if (ret->pixels == NULL)
353 goto fail;
354
355 dbg("returning %p", ret);
356 return ret;
357
358fail:
359 free(ret);
360 return NULL;
361}
362
363DECLSPEC int SDLCALL
364SDL_SetColors(SDL_Surface *surface, SDL_Color *colors, int firstcolor, int ncolors)
365{
366 int i, to;
367
368 trace("%p, %p, %d, %d", surface, colors, firstcolor, ncolors);
369
370 if (surface != g_screen)
371 return 0;
372
373 to = min(ARRAY_SIZE(g_8bpp_pal), firstcolor + ncolors);
374 for (i = firstcolor; i < to; i++) {
375 SDL_Color *c = &colors[i - firstcolor];
376 int r = c->r, g = c->g, b = c->b;
377 // noiz2sa gets a good deal darker that real SDL,
378 // don't know what's going on there
379/*
380 if (r < 0xf8 && (r & 7) > 3) r += 8;
381 if (g < 0xfc && (g & 3) > 1) g += 4;
382 if (b < 0xf8 && (b & 7) > 3) b += 8;
383*/
384 g_8bpp_pal[i] = ((r << 8) & 0xf800) | ((g << 3) & 0x07e0) | (b >> 3);
385// g_8bpp_pal[i] += 0x0821;
386 }
387
388 return 0;
389}
390
391DECLSPEC int SDLCALL
392SDL_FillRect(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color)
393{
394 trace("%p, %p, %04x", dst, dstrect, color);
395
3cb98c5e 396 if (dst->format->BytesPerPixel != 1) {
397 not_supported();
0ec348b9 398 return -1;
399 }
400 else
401 memset(dst->pixels, color, dst->pitch * dst->h);
402
403 return 0;
404}
405
406/*
407DECLSPEC SDL_Surface * SDLCALL
408SDL_CreateRGBSurfaceFrom(void *pixels, int width, int height, int depth, int pitch,
409 Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
410{
411}
412*/
413
414DECLSPEC SDL_RWops * SDLCALL
415SDL_RWFromFile(const char *file, const char *mode)
416{
417 SDL_RWops *ret;
418 FILE *f;
419
420 trace("%s, %s", file, mode);
421
422 f = fopen(file, mode);
423 if (f == NULL)
424 return NULL;
425
426 ret = calloc(1, sizeof(*ret));
427 if (ret == NULL) {
428 fclose(f);
429 return NULL;
430 }
431 ret->hidden.stdio.fp = f;
432
433 return ret;
434}
435
436DECLSPEC void SDLCALL
437SDL_FreeRW(SDL_RWops *area)
438{
439 if (area->hidden.stdio.fp) {
440 fclose(area->hidden.stdio.fp);
441 area->hidden.stdio.fp = NULL;
442 }
443 free(area);
444}
445
446DECLSPEC SDL_Surface * SDLCALL
447SDL_LoadBMP_RW(SDL_RWops *src, int freesrc)
448{
449 struct bmp_dib_v3 {
450 unsigned char magic[2];
451 uint32_t filesz;
452 uint16_t creator1;
453 uint16_t creator2;
454 uint32_t bmp_offset;
455 uint32_t header_sz;
456 int32_t width;
457 int32_t height;
458 uint16_t nplanes;
459 uint16_t bitspp;
460 uint32_t compress_type;
461 uint32_t bmp_bytesz;
462 int32_t hres;
463 int32_t vres;
464 uint32_t ncolors;
465 uint32_t nimpcolors;
466 } __attribute__((packed)) bmp;
467 SDL_Surface *ret = NULL;
468 int data_size, read_size;
3cb98c5e 469 uint8_t *tmp_buf = NULL;
0ec348b9 470 int i, bytespp;
471 FILE *f;
472
473 trace("%p, %d", src, freesrc);
474
475 f = src->hidden.stdio.fp;
476 if (f == NULL)
477 goto out;
478
479 if (fread(&bmp, 1, sizeof(bmp), f) != sizeof(bmp)) {
480 err("bmp read error");
481 goto out;
482 }
483
484 if (bmp.magic[0] != 'B' || bmp.magic[1] != 'M' || bmp.header_sz != 40) {
485 err("unhandled BMP format, sz=%d", bmp.header_sz);
486 goto out;
487 }
488
489 if ((unsigned)bmp.width > 0xffff || (unsigned)bmp.height > 0xffff) {
490 err("BMP size %dx%d out of range", bmp.width, bmp.height);
491 goto out;
492 }
493
494 if (bmp.bitspp != 4) {
495 err("BMP unhandled bpp: %d", bmp.bitspp);
496 goto out;
497 }
498
499 bytespp = bmp.bitspp < 8 ? 1 : (bmp.bitspp + 7) / 8;
500 data_size = bmp.width * bmp.height * bytespp;
501 tmp_buf = malloc(data_size);
502 if (tmp_buf == NULL)
503 goto out;
504
505 if (fseek(f, bmp.bmp_offset, SEEK_SET) != 0) {
506 err("BMP seek error");
507 goto out;
508 }
509
510 read_size = bmp.width * bmp.bitspp / 8;
511 for (i = bmp.height - 1; i > 0; i--) {
512 if (fread((char *)tmp_buf + i * read_size, 1, read_size, f) != read_size) {
513 err("BMP read error");
514 goto out;
515 }
516 }
517
518 if (bmp.bitspp == 4) {
519 // just convert to 8bpp now
520 int c = bmp.width * bmp.height / 2;
521 uint8_t *p = tmp_buf;
522 for (i = c - 1; i >= 0; i--) {
523 p[i * 2 + 1] = p[i] & 0xf;
524 p[i * 2] = p[i] >> 4;
525 }
526 }
527
528 ret = alloc_surface(bmp.width, bmp.height, 8);
529 if (ret == NULL)
530 goto out;
531
532 ret->pixels = tmp_buf;
533 tmp_buf = NULL;
534
535out:
536 if (tmp_buf != NULL)
537 free(tmp_buf);
538 if (freesrc)
539 SDL_FreeRW(src);
540
541 return ret;
542}
543
544DECLSPEC SDL_Surface * SDLCALL
545SDL_ConvertSurface(SDL_Surface *src, SDL_PixelFormat *fmt, Uint32 flags)
546{
547 SDL_Surface *ret;
548 void *data;
549
550 trace("%p, %p, %08x", src, fmt, flags);
551
552 if (src->format->BitsPerPixel != fmt->BitsPerPixel) {
553 err("convert: not implemented");
554 return NULL;
555 }
556
557 data = malloc(src->pitch * src->h);
558 if (data == NULL)
559 return NULL;
560 memcpy(data, src->pixels, src->pitch * src->h);
561
562 ret = alloc_surface(src->w, src->h, fmt->BitsPerPixel);
563 if (ret == NULL) {
564 free(data);
565 return NULL;
566 }
567 ret->pixels = data;
568 return ret;
569}
570
571DECLSPEC int SDLCALL
572SDL_SetColorKey(SDL_Surface *surface, Uint32 flag, Uint32 key)
573{
574 trace("%p, %08x, %04x", surface, flag, key);
575 return 0;
576}
577
0ec348b9 578DECLSPEC void SDLCALL
579SDL_WM_SetCaption(const char *title, const char *icon)
580{
581 trace("%s, %s", title, icon);
582}
583
584DECLSPEC int SDLCALL
585SDL_ShowCursor(int toggle)
586{
587 trace("%d", toggle);
588 return 0;
589}
590
591DECLSPEC char * SDLCALL
592SDL_GetError(void)
593{
594 trace("");
595
596 return "";
597}
598