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