move around - flatter.
[profile/ivi/evas.git] / src / modules / engines / software_sdl / evas_engine.c
1 #include <assert.h>
2 #include <math.h>
3 #include <string.h>
4 #include <sys/time.h>
5 #include <time.h>
6 #include <SDL/SDL.h>
7
8 #include "evas_engine.h"
9
10 /* #define DEBUG_SDL */
11
12 static Evas_Func        func = {};
13 static Evas_Func        pfunc = {};
14
15 static void*                     _sdl_output_setup      (int w, int h, int fullscreen, int noframe, int alpha, int hwsurface);
16
17 static Engine_Image_Entry       *_sdl_image_alloc       (void);
18 static void                      _sdl_image_delete      (Engine_Image_Entry *eim);
19
20 static int                       _sdl_image_constructor (Engine_Image_Entry*, void* data);
21 static void                      _sdl_image_destructor  (Engine_Image_Entry *eim);
22
23 static void                      _sdl_image_dirty_region(Engine_Image_Entry *eim, int x, int y, int w, int h);
24
25 static int                       _sdl_image_dirty       (Engine_Image_Entry *dst, const Engine_Image_Entry *src);
26
27 static int                       _sdl_image_size_set    (Engine_Image_Entry *dst, const Engine_Image_Entry *src);
28
29 static int                       _sdl_image_update_data (Engine_Image_Entry* dst, void* engine_data);
30
31 static void                      _sdl_image_load        (Engine_Image_Entry *eim, const Image_Entry* im);
32 static int                       _sdl_image_mem_size_get(Engine_Image_Entry *eim);
33
34 #ifdef DEBUG_SDL
35 static void                      _sdl_image_debug       (const char* context, Engine_Image_Entry* im);
36 #endif
37
38 static const Evas_Cache_Engine_Image_Func       _sdl_cache_engine_image_cb = {
39   NULL /* key */,
40   _sdl_image_alloc /* alloc */,
41   _sdl_image_delete /* dealloc */,
42   _sdl_image_constructor /* constructor */,
43   _sdl_image_destructor /* destructor */,
44   _sdl_image_dirty_region /* dirty_region */,
45   _sdl_image_dirty /* dirty */,
46   _sdl_image_size_set /* size_set */,
47   _sdl_image_update_data /* update_data */,
48   _sdl_image_load /* load */,
49   _sdl_image_mem_size_get /* mem_size_get */,
50 #ifdef DEBUG_SDL  /* debug */
51   _sdl_image_debug
52 #else
53   NULL
54 #endif
55 };
56
57 #define _SDL_UPDATE_PIXELS(EIM)                                 \
58   ((RGBA_Image *) EIM->cache_entry.src)->image.data = EIM->surface->pixels;
59
60 #define RMASK 0x00ff0000
61 #define GMASK 0x0000ff00
62 #define BMASK 0x000000ff
63 #define AMASK 0xff000000
64
65 /* SDL engine info function */
66 static void*
67 evas_engine_sdl_info            (Evas* e)
68 {
69    Evas_Engine_Info_SDL*        info = calloc(1, sizeof (Evas_Engine_Info_SDL));
70
71    if (!info)
72       return NULL;
73
74    info->magic.magic = rand();
75
76    return info;
77 }
78
79 static void
80 evas_engine_sdl_info_free       (Evas* e, void* info)
81 {
82    Evas_Engine_Info_SDL*        in = (Evas_Engine_Info_SDL*) info;
83
84    free(in);
85    in = NULL;
86 }
87
88 /* SDL engine output manipulation function */
89 static void
90 evas_engine_sdl_setup           (Evas* e, void* in)
91 {
92    Evas_Engine_Info_SDL*        info = (Evas_Engine_Info_SDL*) in;
93
94    /* if we arent set to sdl, why the hell do we get called?! */
95    if (evas_output_method_get(e) != evas_render_method_lookup("software_sdl"))
96       return ;
97
98    SDL_Init(SDL_INIT_NOPARACHUTE);
99
100    if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
101      {
102         fprintf(stderr, "SDL_Init failed with %s\n", SDL_GetError());
103         exit(-1);
104      }
105
106    /* lets just set up */
107    e->engine.data.output = _sdl_output_setup(e->output.w, e->output.h,
108                                              info->info.fullscreen,
109                                              info->info.noframe,
110                                              info->info.alpha,
111                                              info->info.hwsurface);
112
113    if (!e->engine.data.output)
114       return;
115
116    e->engine.func = &func;
117    e->engine.data.context = e->engine.func->context_new(e->engine.data.output);
118 }
119
120 static void
121 evas_engine_sdl_output_free     (void *data)
122 {
123    Render_Engine*               re = data;
124
125    if (re->cache)
126      evas_cache_engine_image_shutdown(re->cache);
127
128    evas_common_tilebuf_free(re->tb);
129    if (re->rects)
130       evas_common_tilebuf_free_render_rects(re->rects);
131
132    if (re->update_rects)
133      free(re->update_rects);
134    free(re);
135
136 /*    evas_common_font_shutdown(); */
137    evas_common_image_shutdown();
138
139    SDL_QuitSubSystem(SDL_INIT_VIDEO);
140 }
141
142 static void
143 evas_engine_sdl_output_resize   (void *data, int w, int h)
144 {
145    /* FIXME */
146    Render_Engine        *re = data;
147    SDL_Surface          *surface;
148
149    if (w == re->tb->outbuf_w && h == re->tb->outbuf_h)
150      return;
151
152    /* Destroy the current screen */
153    evas_cache_engine_image_drop(&re->rgba_engine_image->cache_entry);
154
155    /* Rebuil tilebuf */
156    evas_common_tilebuf_free(re->tb);
157    re->tb = evas_common_tilebuf_new(w, h);
158    if (re->tb)
159       evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE);
160
161    /* Build the new screen */
162    surface = SDL_SetVideoMode(w, h, 32,
163                               (re->flags.hwsurface ? SDL_HWSURFACE : SDL_SWSURFACE)
164                               | (re->flags.fullscreen ? SDL_FULLSCREEN : 0)
165                               | (re->flags.noframe ? SDL_NOFRAME : 0)
166                               | (re->flags.alpha ? SDL_SRCALPHA : 0));
167
168    if (!surface)
169      {
170         fprintf(stderr, "Unable to change the resolution to : %ix%i\n", w, h);
171         exit(-1);
172      }
173    re->rgba_engine_image = (SDL_Engine_Image_Entry *) evas_cache_engine_image_engine(re->cache, surface);
174    if (!re->rgba_engine_image)
175      {
176         fprintf(stderr, "RGBA_Image allocation from SDL failed\n");
177         exit(-1);
178      }
179
180    SDL_FillRect(surface, NULL, 0);
181 }
182
183 static void
184 evas_engine_sdl_output_tile_size_set    (void *data, int w, int h)
185 {
186    Render_Engine*                       re = (Render_Engine*) data;
187
188    evas_common_tilebuf_set_tile_size(re->tb, w, h);
189 }
190
191 static void
192 evas_engine_sdl_output_redraws_rect_add (void *data, int x, int y, int w, int h)
193 {
194    Render_Engine*                       re = (Render_Engine*) data;
195
196    evas_common_tilebuf_add_redraw(re->tb, x, y, w, h);
197 }
198
199 static void
200 evas_engine_sdl_output_redraws_rect_del (void *data, int x, int y, int w, int h)
201 {
202    Render_Engine*                       re = (Render_Engine*) data;
203
204    evas_common_tilebuf_del_redraw(re->tb, x, y, w, h);
205 }
206
207 static void
208 evas_engine_sdl_output_redraws_clear    (void *data)
209 {
210    Render_Engine*                       re = (Render_Engine*) data;
211
212    evas_common_tilebuf_clear(re->tb);
213 }
214
215 static void*
216 evas_engine_sdl_output_redraws_next_update_get  (void *data,
217                                                  int *x, int *y, int *w, int *h,
218                                                  int *cx, int *cy, int *cw, int *ch)
219 {
220    Render_Engine        *re = data;
221    Tilebuf_Rect         *tb_rect;
222    SDL_Rect              rect;
223
224    if (re->flags.end)
225      {
226         re->flags.end = 0;
227         return NULL;
228      }
229    if (!re->rects)
230      {
231         re->rects = evas_common_tilebuf_get_render_rects(re->tb);
232         re->cur_rect = (Evas_Object_List *) re->rects;
233      }
234    if (!re->cur_rect)
235       return NULL;
236
237    tb_rect = (Tilebuf_Rect*) re->cur_rect;
238    *cx = *x = tb_rect->x;
239    *cy = *y = tb_rect->y;
240    *cw = *w = tb_rect->w;
241    *ch = *h = tb_rect->h;
242    re->cur_rect = re->cur_rect->next;
243    if (!re->cur_rect)
244      {
245         evas_common_tilebuf_free_render_rects(re->rects);
246         re->rects = NULL;
247         re->flags.end = 1;
248      }
249
250    rect.x = *x;
251    rect.y = *y;
252    rect.w = *w;
253    rect.h = *h;
254
255    SDL_FillRect(re->rgba_engine_image->surface, &rect, 0);
256
257    /* Return the "fake" surface so it is passed to the drawing routines. */
258    return re->rgba_engine_image;
259 }
260
261 static void
262 evas_engine_sdl_output_redraws_next_update_push (void *data, void *surface,
263                                                  int x, int y, int w, int h)
264 {
265    Render_Engine                                *re = (Render_Engine *) data;
266
267    if (re->update_rects_count + 1 > re->update_rects_limit)
268      {
269         re->update_rects_limit += 8;
270         re->update_rects = realloc(re->update_rects, sizeof (SDL_Rect) * re->update_rects_limit);
271      }
272
273    re->update_rects[re->update_rects_count].x = x;
274    re->update_rects[re->update_rects_count].y = y;
275    re->update_rects[re->update_rects_count].w = w;
276    re->update_rects[re->update_rects_count].h = h;
277
278    ++re->update_rects_count;
279
280    evas_common_cpu_end_opt();
281 }
282
283 static void
284 _sdl_image_dirty_region(Engine_Image_Entry *eim, int x, int y, int w, int h)
285 {
286    SDL_Engine_Image_Entry       *dst;
287    RGBA_Image *im;
288
289    dst = (SDL_Engine_Image_Entry *) eim;
290
291    SDL_UpdateRect(dst->surface, x, y, w, h);
292
293    im = (RGBA_Image *)eim->src;
294    im->flags |= RGBA_IMAGE_IS_DIRTY;
295 }
296
297 static void
298 evas_engine_sdl_output_flush(void *data)
299 {
300    Render_Engine        *re = (Render_Engine *) data;
301
302    if (re->update_rects_count > 0)
303      SDL_UpdateRects(re->rgba_engine_image->surface, re->update_rects_count, re->update_rects);
304
305    re->update_rects_count = 0;
306 }
307
308
309 static void
310 evas_engine_sdl_output_idle_flush(void *data)
311 {
312    (void) data;
313 }
314
315 /*
316  * Image objects
317  */
318
319 static void*
320 evas_engine_sdl_image_load(void *data, const char *file, const char *key, int *error, Evas_Image_Load_Opts *lo)
321 {
322    Render_Engine*       re = (Render_Engine*) data;;
323
324    *error = 0;
325    return evas_cache_engine_image_request(re->cache, file, key, lo, NULL, error);
326 }
327
328 static int
329 evas_engine_sdl_image_alpha_get(void *data, void *image)
330 {
331    SDL_Engine_Image_Entry       *eim = image;
332    RGBA_Image                   *im;
333
334    if (!eim) return 1;
335    im = (RGBA_Image *) eim->cache_entry.src;
336    switch (eim->cache_entry.src->space)
337      {
338      case EVAS_COLORSPACE_ARGB8888:
339         if (im->cache_entry.flags.alpha) return 1;
340      default:
341         break;
342      }
343    return 0;
344 }
345
346 static void
347 evas_engine_sdl_image_size_get(void *data, void *image, int *w, int *h)
348 {
349    SDL_Engine_Image_Entry       *eim;
350
351    eim = image;
352    if (w) *w = eim->cache_entry.src->w;
353    if (h) *h = eim->cache_entry.src->h;
354 }
355
356 static int
357 evas_engine_sdl_image_colorspace_get(void *data, void *image)
358 {
359    SDL_Engine_Image_Entry       *eim = image;
360
361    if (!eim) return EVAS_COLORSPACE_ARGB8888;
362    return eim->cache_entry.src->space;
363 }
364
365 static void
366 evas_engine_sdl_image_colorspace_set(void *data, void *image, int cspace)
367 {
368    SDL_Engine_Image_Entry       *eim = image;
369
370    if (!eim) return;
371    if (eim->cache_entry.src->space == cspace) return;
372
373    evas_cache_engine_image_colorspace(&eim->cache_entry, cspace, NULL);
374 }
375
376 static void*
377 evas_engine_sdl_image_new_from_copied_data(void *data,
378                                            int w, int h,
379                                            DATA32* image_data,
380                                            int alpha, int cspace)
381 {
382    Render_Engine        *re = (Render_Engine*) data;
383
384    return evas_cache_engine_image_copied_data(re->cache, w, h, image_data, alpha, cspace, NULL);
385 }
386
387 static void*
388 evas_engine_sdl_image_new_from_data(void *data, int w, int h, DATA32* image_data, int alpha, int cspace)
389 {
390    Render_Engine        *re = (Render_Engine*) data;
391
392    return evas_cache_engine_image_data(re->cache, w, h, image_data, alpha, cspace, NULL);
393 }
394
395 static void
396 evas_engine_sdl_image_free(void *data, void *image)
397 {
398    SDL_Engine_Image_Entry       *eim = image;
399
400    (void) data;
401
402    evas_cache_engine_image_drop(&eim->cache_entry);
403 }
404
405 static void*
406 evas_engine_sdl_image_size_set(void *data, void *image, int w, int h)
407 {
408    SDL_Engine_Image_Entry       *eim = image;
409
410    (void) data;
411
412    return evas_cache_engine_image_size_set(&eim->cache_entry, w, h);
413 }
414
415 static void*
416 evas_engine_sdl_image_dirty_region(void *data,
417                                    void *image,
418                                    int x, int y, int w, int h)
419 {
420    SDL_Engine_Image_Entry       *eim = image;
421
422    (void) data;
423
424    return evas_cache_engine_image_dirty(&eim->cache_entry, x, y, w, h);
425 }
426
427 static void*
428 evas_engine_sdl_image_data_get(void *data, void *image,
429                                int to_write, DATA32** image_data)
430 {
431    SDL_Engine_Image_Entry       *eim = image;
432    RGBA_Image                   *im;
433
434    (void) data;
435
436    if (!eim)
437      {
438         *image_data = NULL;
439         return NULL;
440      }
441    im = (RGBA_Image *) eim->cache_entry.src;
442
443    switch (eim->cache_entry.src->space)
444      {
445      case EVAS_COLORSPACE_ARGB8888:
446         if (to_write)
447           eim = (SDL_Engine_Image_Entry *) evas_cache_engine_image_dirty(&eim->cache_entry, 0, 0, eim->cache_entry.src->w, eim->cache_entry.src->h);
448
449         evas_cache_engine_image_load_data(&eim->cache_entry);
450         *image_data = im->image.data;
451         break;
452      case EVAS_COLORSPACE_YCBCR422P709_PL:
453      case EVAS_COLORSPACE_YCBCR422P601_PL:
454         *image_data = im->cs.data;
455         break;
456      default:
457         abort();
458         break;
459      }
460    return eim;
461 }
462
463 static void*
464 evas_engine_sdl_image_data_put(void *data, void *image, DATA32* image_data)
465 {
466    SDL_Engine_Image_Entry       *eim = image;
467    Render_Engine                *re = data;
468    RGBA_Image                   *im;
469
470    if (!eim) return NULL;
471    im = (RGBA_Image*) eim->cache_entry.src;
472
473    switch (eim->cache_entry.src->space)
474      {
475      case EVAS_COLORSPACE_ARGB8888:
476         if (image_data != im->image.data)
477           {
478              evas_cache_engine_image_drop(&eim->cache_entry);
479              eim = (SDL_Engine_Image_Entry *) evas_cache_engine_image_data(re->cache,
480                                                                            eim->cache_entry.w, eim->cache_entry.h,
481                                                                            image_data,
482                                                                            func.image_alpha_get(data, eim),
483                                                                            func.image_colorspace_get(data, eim),
484                                                                            NULL);
485           }
486         break;
487      case EVAS_COLORSPACE_YCBCR422P601_PL:
488      case EVAS_COLORSPACE_YCBCR422P709_PL:
489         if (image_data != im->cs.data)
490           {
491              if (im->cs.data)
492                if (!im->cs.no_free)
493                  free(im->cs.data);
494              im->cs.data = image_data;
495              evas_common_image_colorspace_dirty(im);
496           }
497         break;
498      default:
499         abort();
500         break;
501      }
502    return eim;
503 }
504
505 static void*
506 evas_engine_sdl_image_alpha_set(void *data, void *image, int has_alpha)
507 {
508    SDL_Engine_Image_Entry       *eim = image;
509    RGBA_Image                   *im;
510
511    (void) data;
512
513    if (!eim) return NULL;
514
515    im = (RGBA_Image *) eim->cache_entry.src;
516
517    if (eim->cache_entry.src->space != EVAS_COLORSPACE_ARGB8888)
518      {
519         im->cache_entry.flags.alpha = 0;
520         return eim;
521      }
522
523    eim = (SDL_Engine_Image_Entry *) evas_cache_engine_image_dirty(&eim->cache_entry, 0, 0, eim->cache_entry.w, eim->cache_entry.h);
524
525    /* FIXME: update SDL_Surface flags */
526    im->cache_entry.flags.alpha = has_alpha ? 1 : 0;
527    return eim;
528 }
529
530 static void*
531 evas_engine_sdl_image_border_set(void *data, void *image, int l, int r, int t, int b)
532 {
533    return image;
534 }
535
536 static void
537 evas_engine_sdl_image_border_get(void *data, void *image, int *l, int *r, int *t, int *b)
538 {
539    /* FIXME: need to know what evas expect from this call */
540 }
541
542 static void
543 evas_engine_sdl_image_draw(void *data, void *context, void *surface, void *image,
544                            int src_region_x, int src_region_y, int src_region_w, int src_region_h,
545                            int dst_region_x, int dst_region_y, int dst_region_w, int dst_region_h,
546                            int smooth)
547 {
548    SDL_Engine_Image_Entry       *eim = image;
549    SDL_Engine_Image_Entry       *dst = surface;
550    RGBA_Draw_Context            *dc = (RGBA_Draw_Context*) context;
551    int                           mustlock_im = 0;
552    int                           mustlock_dst = 0;
553
554    (void) data;
555
556    if (eim->cache_entry.src->space == EVAS_COLORSPACE_ARGB8888)
557      evas_cache_engine_image_load_data(&eim->cache_entry);
558
559    /* Fallback to software method */
560    if (SDL_MUSTLOCK(dst->surface))
561      {
562         mustlock_dst = 1;
563         SDL_LockSurface(dst->surface);
564         _SDL_UPDATE_PIXELS(dst);
565      }
566
567    if (eim->surface && SDL_MUSTLOCK(eim->surface))
568      {
569         mustlock_im = 1;
570         SDL_LockSurface(eim->surface);
571         _SDL_UPDATE_PIXELS(eim);
572      }
573
574    evas_common_image_colorspace_normalize((RGBA_Image *) eim->cache_entry.src);
575
576    if (smooth)
577      evas_common_scale_rgba_in_to_out_clip_smooth((RGBA_Image *) eim->cache_entry.src,
578                                                   (RGBA_Image *) dst->cache_entry.src,
579                                                   dc,
580                                                   src_region_x, src_region_y, src_region_w, src_region_h,
581                                                   dst_region_x, dst_region_y, dst_region_w, dst_region_h);
582    else
583      evas_common_scale_rgba_in_to_out_clip_sample((RGBA_Image *) eim->cache_entry.src,
584                                                   (RGBA_Image *) dst->cache_entry.src,
585                                                   dc,
586                                                   src_region_x, src_region_y, src_region_w, src_region_h,
587                                                   dst_region_x, dst_region_y, dst_region_w, dst_region_h);
588    evas_common_cpu_end_opt ();
589
590    if (mustlock_im)
591      SDL_UnlockSurface(eim->surface);
592
593    if (mustlock_dst)
594      SDL_UnlockSurface(dst->surface);
595 }
596
597 static void
598 evas_engine_sdl_image_cache_flush(void *data)
599 {
600    Render_Engine        *re = (Render_Engine*) data;
601    int                   size;
602
603    size = evas_cache_engine_image_get(re->cache);
604    evas_cache_engine_image_set(re->cache, 0);
605    evas_cache_engine_image_set(re->cache, size);
606 }
607
608 static void
609 evas_engine_sdl_image_cache_set(void *data, int bytes)
610 {
611    Render_Engine        *re = (Render_Engine*) data;
612
613    evas_cache_engine_image_set(re->cache, bytes);
614 }
615
616 static int
617 evas_engine_sdl_image_cache_get(void *data)
618 {
619    Render_Engine        *re = (Render_Engine*) data;
620
621    return evas_cache_engine_image_get(re->cache);
622 }
623
624 static char*
625 evas_engine_sdl_image_comment_get(void *data, void *image, char *key)
626 {
627    SDL_Engine_Image_Entry       *eim = image;
628    RGBA_Image                   *im;
629
630    if (!eim) return NULL;
631    im = (RGBA_Image *) eim->cache_entry.src;
632
633    return im->info.comment;
634 }
635
636 static char*
637 evas_engine_sdl_image_format_get(void *data, void *image)
638 {
639    /* FIXME: need to know what evas expect from this call */
640    return NULL;
641 }
642
643 static void
644 evas_engine_sdl_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const char *text)
645 {
646    SDL_Engine_Image_Entry       *eim = surface;
647    int                           mustlock_im = 0;
648
649    if (eim->surface && SDL_MUSTLOCK(eim->surface))
650      {
651         mustlock_im = 1;
652         SDL_LockSurface(eim->surface);
653         _SDL_UPDATE_PIXELS(eim);
654      }
655
656    evas_common_font_draw((RGBA_Image *) eim->cache_entry.src, context, font, x, y, text);
657    evas_common_cpu_end_opt();
658
659    if (mustlock_im)
660      SDL_UnlockSurface(eim->surface);
661 }
662
663 static void
664 evas_engine_sdl_line_draw(void *data, void *context, void *surface, int x1, int y1, int x2, int y2)
665 {
666    SDL_Engine_Image_Entry       *eim = surface;
667    int                           mustlock_im = 0;
668
669    if (eim->surface && SDL_MUSTLOCK(eim->surface))
670      {
671         mustlock_im = 1;
672         SDL_LockSurface(eim->surface);
673         _SDL_UPDATE_PIXELS(eim);
674      }
675
676    evas_common_line_draw((RGBA_Image *) eim->cache_entry.src, context, x1, y1, x2, y2);
677    evas_common_cpu_end_opt();
678
679    if (mustlock_im)
680      SDL_UnlockSurface(eim->surface);
681 }
682
683 static void
684 evas_engine_sdl_rectangle_draw(void *data, void *context, void *surface, int x, int y, int w, int h)
685 {
686    SDL_Engine_Image_Entry       *eim = surface;
687 #if ENGINE_SDL_PRIMITIVE
688    RGBA_Draw_Context            *dc = context;
689 #endif
690    int                           mustlock_im = 0;
691
692 #if ENGINE_SDL_PRIMITIVE
693    if (A_VAL(&dc->col.col) != 0x00)
694      {
695         if (A_VAL(&dc->col.col) != 0xFF)
696           {
697 #endif
698              if (eim->surface && SDL_MUSTLOCK(eim->surface))
699                {
700                   mustlock_im = 1;
701                   SDL_LockSurface(eim->surface);
702                   _SDL_UPDATE_PIXELS(eim);
703                }
704
705              evas_common_rectangle_draw((RGBA_Image *) eim->cache_entry.src, context, x, y, w, h);
706              evas_common_cpu_end_opt();
707
708              if (mustlock_im)
709                SDL_UnlockSurface(eim->surface);
710 #if ENGINE_SDL_PRIMITIVE
711           }
712         else
713           {
714              SDL_Rect        dstrect;
715
716              if (dc->clip.use)
717                {
718                   SDL_Rect   cliprect;
719
720                   cliprect.x = dc->clip.x;
721                   cliprect.y = dc->clip.y;
722                   cliprect.w = dc->clip.w;
723                   cliprect.h = dc->clip.h;
724
725                   SDL_SetClipRect(eim->surface, &cliprect);
726                }
727
728              dstrect.x = x;
729              dstrect.y = y;
730              dstrect.w = w;
731              dstrect.h = h;
732
733              SDL_FillRect(eim->surface, &dstrect, SDL_MapRGBA(eim->surface->format, R_VAL(&dc->col.col), G_VAL(&dc->col.col), B_VAL(&dc->col.col), 0xFF));
734
735              if (dc->clip.use)
736                SDL_SetClipRect(eim->surface, NULL);
737           }
738      }
739 #endif
740 }
741
742 static void
743 evas_engine_sdl_polygon_draw(void *data, void *context, void *surface, void *polygon)
744 {
745    SDL_Engine_Image_Entry       *eim = surface;
746    int                           mustlock_im = 0;
747
748    if (eim->surface && SDL_MUSTLOCK(eim->surface))
749      {
750         mustlock_im = 1;
751         SDL_LockSurface(eim->surface);
752         _SDL_UPDATE_PIXELS(eim);
753      }
754
755    evas_common_polygon_draw((RGBA_Image *) eim->cache_entry.src, context, polygon);
756    evas_common_cpu_end_opt();
757
758    if (mustlock_im)
759      SDL_UnlockSurface(eim->surface);
760 }
761
762 static void
763 evas_engine_sdl_gradient_draw(void *data, void *context, void *surface, void *gradient, int x, int y, int w, int h)
764 {
765    SDL_Engine_Image_Entry       *eim = surface;
766    int                           mustlock_im = 0;
767
768    if (eim->surface && SDL_MUSTLOCK(eim->surface))
769      {
770         mustlock_im = 1;
771         SDL_LockSurface(eim->surface);
772         _SDL_UPDATE_PIXELS(eim);
773      }
774
775    evas_common_gradient_draw((RGBA_Image *) eim->cache_entry.src, context, x, y, w, h, gradient);
776    evas_common_cpu_end_opt();
777
778    if (mustlock_im)
779      SDL_UnlockSurface(eim->surface);
780 }
781
782 EAPI int module_open(Evas_Module *em)
783 {
784    if (!em) return 0;
785    /* get whatever engine module we inherit from */
786    if (!_evas_module_engine_inherit(&pfunc, "software_generic")) return 0;
787    /* store it for later use */
788    func = pfunc;
789    /* now to override methods */
790 #define ORD(f) EVAS_API_OVERRIDE(f, &func, evas_engine_sdl_)
791    ORD(info);
792    ORD(info_free);
793    ORD(setup);
794    ORD(output_free);
795    ORD(output_resize);
796    ORD(output_tile_size_set);
797    ORD(output_redraws_rect_add);
798    ORD(output_redraws_rect_del);
799    ORD(output_redraws_clear);
800    ORD(output_redraws_next_update_get);
801    ORD(output_redraws_next_update_push);
802    ORD(output_flush);
803    ORD(output_idle_flush);
804    ORD(image_load);
805    ORD(image_new_from_data);
806    ORD(image_new_from_copied_data);
807    ORD(image_colorspace_set);
808    ORD(image_colorspace_get);
809    ORD(image_free);
810    ORD(image_size_set);
811    ORD(image_size_get);
812    ORD(image_dirty_region);
813    ORD(image_data_get);
814    ORD(image_data_put);
815    ORD(image_alpha_set);
816    ORD(image_alpha_get);
817    ORD(image_border_set);
818    ORD(image_border_get);
819    ORD(image_draw);
820    ORD(image_comment_get);
821    ORD(image_format_get);
822    ORD(image_cache_flush);
823    ORD(image_cache_set);
824    ORD(image_cache_get);
825    ORD(font_draw);
826    ORD(line_draw);
827    ORD(rectangle_draw);
828    ORD(polygon_draw);
829    ORD(gradient_draw);
830    /* now advertise out own api */
831    em->functions = (void *)(&func);
832    return 1;
833 }
834
835 EAPI void module_close(void)
836 {
837
838 }
839
840 EAPI Evas_Module_Api evas_modapi =
841 {
842    EVAS_MODULE_API_VERSION,
843    EVAS_MODULE_TYPE_ENGINE,
844    "software_sdl",
845    "none"
846 };
847
848 /* Private routines. */
849
850 static void*
851 _sdl_output_setup               (int w, int h, int fullscreen, int noframe, int alpha, int hwsurface)
852 {
853    Render_Engine                *re = calloc(1, sizeof(Render_Engine));
854    SDL_Surface                  *surface;
855
856    /* if we haven't initialized - init (automatic abort if already done) */
857    evas_common_cpu_init();
858    evas_common_blend_init();
859    evas_common_image_init();
860    evas_common_convert_init();
861    evas_common_scale_init();
862    evas_common_rectangle_init();
863    evas_common_gradient_init();
864    evas_common_polygon_init();
865    evas_common_line_init();
866    evas_common_font_init();
867    evas_common_draw_init();
868    evas_common_tilebuf_init();
869
870    if (w <= 0) w = 640;
871    if (h <= 0) h = 480;
872
873    re->cache = evas_cache_engine_image_init(&_sdl_cache_engine_image_cb, evas_common_image_cache_get());
874    if (!re->cache)
875      {
876         fprintf(stderr, "Evas_Cache_Engine_Image allocation failed!\n");
877         exit(-1);
878      }
879
880    re->tb = evas_common_tilebuf_new(w, h);
881    /* in preliminary tests 16x16 gave highest framerates */
882    evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE);
883    surface = SDL_SetVideoMode(w, h, 32,
884                               (hwsurface ? SDL_HWSURFACE : SDL_SWSURFACE)
885                               | (fullscreen ? SDL_FULLSCREEN : 0)
886                               | (noframe ? SDL_NOFRAME : 0)
887                               | (alpha ? SDL_SRCALPHA : 0));
888
889    if (!surface)
890      {
891         fprintf(stderr, "SDL_SetVideoMode [ %i x %i x 32 ] failed.\n", w, h);
892         exit(-1);
893      }
894
895    SDL_SetAlpha(surface, SDL_SRCALPHA | SDL_RLEACCEL, 0);
896
897    /* We create a "fake" RGBA_Image which points to the SDL surface. Each access
898     * to that surface is wrapped in Lock / Unlock calls whenever the data is
899     * manipulated directly. */
900    re->rgba_engine_image = (SDL_Engine_Image_Entry *) evas_cache_engine_image_engine(re->cache, surface);
901    if (!re->rgba_engine_image)
902      {
903         fprintf(stderr, "RGBA_Image allocation from SDL failed\n");
904         exit(-1);
905      }
906
907    SDL_FillRect(surface, NULL, 0);
908
909    re->flags.alpha = alpha;
910    re->flags.hwsurface = hwsurface;
911    re->flags.fullscreen = fullscreen;
912    re->flags.noframe = noframe;
913    return re;
914 }
915
916 static Engine_Image_Entry*
917 _sdl_image_alloc(void)
918 {
919    SDL_Engine_Image_Entry       *new;
920
921    new = calloc(1, sizeof (SDL_Engine_Image_Entry));
922
923    return (Engine_Image_Entry *) new;
924 }
925
926 static void
927 _sdl_image_delete(Engine_Image_Entry *eim)
928 {
929    free(eim);
930 }
931
932 static int
933 _sdl_image_constructor(Engine_Image_Entry *ie, void *data)
934 {
935    SDL_Surface                  *sdl = NULL;
936    SDL_Engine_Image_Entry       *eim = (SDL_Engine_Image_Entry *) ie;
937    RGBA_Image                   *im;
938
939    im = (RGBA_Image *) ie->src;
940
941    if (im)
942      {
943         evas_cache_image_load_data(&im->cache_entry);
944
945         if (im->image.data)
946           {
947              /* FIXME: Take care of CSPACE */
948              sdl = SDL_CreateRGBSurfaceFrom(im->image.data,
949                                             ie->w, ie->h,
950                                             32, ie->w * 4,
951                                             RMASK, GMASK, BMASK, AMASK);
952              eim->surface = sdl;
953              eim->flags.engine_surface = 0;
954           }
955      }
956
957    return 0;
958 }
959
960 static void
961 _sdl_image_destructor(Engine_Image_Entry *eie)
962 {
963    SDL_Engine_Image_Entry       *seie = (SDL_Engine_Image_Entry *) eie;
964
965    if (seie->surface && !seie->flags.engine_surface)
966      SDL_FreeSurface(seie->surface);
967    seie->surface = NULL;
968 }
969
970 static int
971 _sdl_image_dirty(Engine_Image_Entry *dst, const Engine_Image_Entry *src)
972 {
973    SDL_Engine_Image_Entry       *eim = (SDL_Engine_Image_Entry *) dst;
974    SDL_Surface                  *sdl = NULL;
975    RGBA_Image                   *im;
976
977    im = (RGBA_Image *) dst->src;
978
979    /* FIXME: Take care of CSPACE */
980    sdl = SDL_CreateRGBSurfaceFrom(im->image.data,
981                                   dst->w, dst->h,
982                                   32, dst->w * 4,
983                                   0xff0000, 0xff00, 0xff, 0xff000000);
984    eim->surface = sdl;
985    eim->flags.engine_surface = 0;
986
987    return 0;
988 }
989
990 static int
991 _sdl_image_update_data(Engine_Image_Entry *dst, void* engine_data)
992 {
993    SDL_Engine_Image_Entry       *eim = (SDL_Engine_Image_Entry *) dst;
994    SDL_Surface                  *sdl = NULL;
995    RGBA_Image                   *im;
996
997    im = (RGBA_Image *) dst->src;
998
999    if (engine_data)
1000      {
1001         sdl = engine_data;
1002
1003         if (im)
1004           {
1005              im->image.data = sdl->pixels;
1006              im->image.no_free = 1;
1007              im->cache_entry.flags.alpha = 0;
1008              dst->src->w = sdl->w;
1009              dst->src->h = sdl->h;
1010           }
1011         dst->w = sdl->w;
1012         dst->h = sdl->h;
1013      }
1014    else
1015      {
1016         /* FIXME: Take care of CSPACE */
1017         SDL_FreeSurface(eim->surface);
1018         sdl = SDL_CreateRGBSurfaceFrom(im->image.data,
1019                                        dst->w, dst->h,
1020                                        32, dst->w * 4,
1021                                        RMASK, GMASK, BMASK, AMASK);
1022      }
1023
1024    eim->surface = sdl;
1025
1026    return 0;
1027 }
1028
1029 static int
1030 _sdl_image_size_set(Engine_Image_Entry *dst, const Engine_Image_Entry *src)
1031 {
1032    SDL_Engine_Image_Entry       *eim = (SDL_Engine_Image_Entry *) dst;
1033    SDL_Surface                  *sdl;
1034    RGBA_Image                   *im;
1035
1036    im = (RGBA_Image *) dst->src;
1037
1038    /* FIXME: handle im == NULL */
1039    sdl = SDL_CreateRGBSurfaceFrom(im->image.data,
1040                                   dst->w, dst->h,
1041                                   32, dst->w * 4,
1042                                   RMASK, GMASK, BMASK, AMASK);
1043
1044    eim->surface = sdl;
1045
1046    return 0;
1047 }
1048
1049 static void
1050 _sdl_image_load(Engine_Image_Entry *eim, const Image_Entry *ie_im)
1051 {
1052    SDL_Engine_Image_Entry       *load = (SDL_Engine_Image_Entry *) eim;
1053    SDL_Surface                  *sdl;
1054
1055    if (!load->surface)
1056      {
1057         RGBA_Image      *im;
1058
1059         im = (RGBA_Image *) ie_im;
1060
1061         sdl = SDL_CreateRGBSurfaceFrom(im->image.data,
1062                                        eim->w, eim->h,
1063                                        32, eim->w * 4,
1064                                        RMASK, GMASK, BMASK, AMASK);
1065         load->surface = sdl;
1066      }
1067 }
1068
1069 static int
1070 _sdl_image_mem_size_get(Engine_Image_Entry *eim)
1071 {
1072    SDL_Engine_Image_Entry       *seie = (SDL_Engine_Image_Entry *) eim;
1073    int                           size = 0;
1074
1075    /* FIXME: Count surface size. */
1076    if (seie->surface)
1077      size = sizeof (SDL_Surface) + sizeof (SDL_PixelFormat);
1078
1079    return size;
1080 }
1081
1082 #ifdef DEBUG_SDL
1083 static void
1084 _sdl_image_debug(const char* context, Engine_Image_Entry* eie)
1085 {
1086    SDL_Engine_Image_Entry       *eim = (SDL_Engine_Image_Entry *) eie;
1087
1088    printf ("*** %s image (%p) ***\n", context, eim);
1089    if (eim)
1090      {
1091         printf ("* W: %i\n* H: %i\n* R: %i\n", eim->cache_entry.w, eim->cache_entry.h, eim->cache_entry.references);
1092         if (eim->cache_entry.src)
1093           printf ("* Pixels: %p\n* SDL Surface: %p\n",((RGBA_Image*) eim->cache_entry.src)->image.data, eim->surface);
1094         if (eim->surface)
1095           printf ("* Surface->pixels: %p\n", eim->surface->pixels);
1096         printf ("* Key: %s\n", eim->cache_entry.cache_key);
1097         printf ("* Reference: %i\n", eim->cache_entry.references);
1098      }
1099    printf ("*** ***\n");
1100 }
1101 #endif