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