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