53e1995f14f140bcbb607615d470776e0376a2ec
[framework/uifw/evas.git] / src / modules / engines / software_16_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_common.h"/* Also includes international specific stuff */
9 #include "evas_engine.h"
10 int _evas_engine_soft16_sdl_log_dom = -1;
11
12 /* function tables - filled in later (func and parent func) */
13 static Evas_Func func, pfunc;
14
15 static Engine_Image_Entry       *_sdl16_image_alloc       (void);
16 static void                      _sdl16_image_delete      (Engine_Image_Entry *eim);
17
18 static int                       _sdl16_image_constructor (Engine_Image_Entry *ie, void* data);
19 static void                      _sdl16_image_destructor  (Engine_Image_Entry *eim);
20
21 static void                      _sdl16_image_dirty_region(Engine_Image_Entry *eim, unsigned int x, unsigned int y, unsigned int w, unsigned int h);
22
23 static int                       _sdl16_image_dirty       (Engine_Image_Entry *dst, const Engine_Image_Entry *src);
24
25 static int                       _sdl16_image_size_set    (Engine_Image_Entry *dst, const Engine_Image_Entry *src);
26
27 static int                       _sdl16_image_update_data (Engine_Image_Entry* dst, void* engine_data);
28
29 static void                      _sdl16_image_load        (Engine_Image_Entry *eim, const Image_Entry* im);
30 static int                       _sdl16_image_mem_size_get(Engine_Image_Entry *eim);
31
32 #ifdef DEBUG_SDL
33 static void                      _sdl16_image_debug       (const char* context, Engine_Image_Entry* im);
34 #endif
35
36 static const Evas_Cache_Engine_Image_Func       _sdl16_cache_engine_image_cb = {
37   NULL /* key */,
38   _sdl16_image_alloc /* alloc */,
39   _sdl16_image_delete /* dealloc */,
40   _sdl16_image_constructor /* constructor */,
41   _sdl16_image_destructor /* destructor */,
42   _sdl16_image_dirty_region /* dirty_region */,
43   _sdl16_image_dirty /* dirty */,
44   _sdl16_image_size_set /* size_set */,
45   _sdl16_image_update_data /* update_data */,
46   _sdl16_image_load /* load */,
47   _sdl16_image_mem_size_get /* mem_size_get */,
48 #ifdef DEBUG_SDL  /* debug */
49   _sdl16_image_debug
50 #else
51   NULL
52 #endif
53 };
54
55 #define _SDL_UPDATE_PIXELS(EIM)                                 \
56   ((Soft16_Image *) EIM->cache_entry.src)->pixels = EIM->surface->pixels;
57
58 #define RMASK565 0xf800
59 #define GMASK565 0x07e0
60 #define BMASK565 0x001f
61 #define AMASK565 0x0000
62
63 /* engine api this module provides */
64 static void *
65 evas_engine_sdl16_info(Evas *e __UNUSED__)
66 {
67    Evas_Engine_Info_SDL_16      *info;
68    info = calloc(1, sizeof(Evas_Engine_Info_SDL_16));
69    if (!info) return NULL;
70    info->magic.magic = rand();
71    return info;
72 }
73
74 static void
75 evas_engine_sdl16_info_free(Evas *e __UNUSED__, void *info)
76 {
77    Evas_Engine_Info_SDL_16 *in;
78    in = (Evas_Engine_Info_SDL_16 *)info;
79    free(in);
80 }
81
82 static void
83 _tmp_out_alloc(Render_Engine *re)
84 {
85    Tilebuf_Rect *r;
86    unsigned int w = 0, h = 0;
87
88    EINA_INLIST_FOREACH(re->rects, r)
89      {
90         if (r->w > (int)w) w = r->w;
91         if (r->h > (int)h) h = r->h;
92      }
93
94    if (re->tmp_out)
95      {
96         if ((re->tmp_out->cache_entry.w < w) || (re->tmp_out->cache_entry.h < h))
97           {
98              evas_cache_image_drop(&re->tmp_out->cache_entry);
99              re->tmp_out = NULL;
100           }
101      }
102
103    if (!re->tmp_out)
104      {
105         Soft16_Image *im;
106
107         im = (Soft16_Image *) evas_cache_image_empty(evas_common_soft16_image_cache_get());
108         im->cache_entry.flags.alpha = 0;
109         evas_cache_image_surface_alloc(&im->cache_entry, w, h);
110
111         re->tmp_out = im;
112      }
113 }
114
115 static void*
116 _sdl16_output_setup(int w, int h, int rotation, int fullscreen, int noframe, int hwsurface)
117 {
118    Render_Engine        *re;
119    SDL_Surface          *surface;
120
121    re = calloc(1, sizeof(Render_Engine));
122    if (!re)
123      return NULL;
124    /* if we haven't initialized - init (automatic abort if already done) */
125    evas_common_cpu_init();
126    evas_common_blend_init();
127    evas_common_image_init();
128    evas_common_convert_init();
129    evas_common_scale_init();
130    evas_common_rectangle_init();
131    evas_common_polygon_init();
132    evas_common_line_init();
133    evas_common_font_init();
134    evas_common_draw_init();
135    evas_common_tilebuf_init();
136    evas_common_soft16_image_init();
137
138    if (w <= 0) w = 640;
139    if (h <= 0) h = 480;
140
141    re->cache = evas_cache_engine_image_init(&_sdl16_cache_engine_image_cb, evas_common_soft16_image_cache_get());
142    if (!re->cache)
143      {
144         ERR("Evas_Cache_Engine_Image allocation failed!");
145         free(re);
146         return NULL;
147      }
148
149    re->tb = evas_common_tilebuf_new(w, h);
150    /* in preliminary tests 16x16 gave highest framerates */
151    evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE);
152    re->w = w;
153    re->h = h;
154    re->rot = rotation;
155    re->flags.hwsurface = hwsurface;
156    re->flags.fullscreen = fullscreen;
157    re->flags.noframe = noframe;
158    re->flags.end = 0;
159
160    re->update_rects_count = 0;
161    re->update_rects_limit = 0;
162    re->update_rects = NULL;
163
164    surface = SDL_SetVideoMode(w, h, 16,
165                               (hwsurface ? SDL_HWSURFACE : SDL_SWSURFACE)
166                               | (fullscreen ? SDL_FULLSCREEN : 0)
167                               | (noframe ? SDL_NOFRAME : 0));
168    if (!surface)
169      {
170         ERR("SDL_SetVideoMode [ %i x %i x 16 ] failed", w, h);
171         evas_cache_engine_image_shutdown(re->cache);
172         free(re);
173         return NULL;
174      }
175
176    SDL_SetAlpha(surface, SDL_RLEACCEL, 0);
177    SDL_FillRect(surface, NULL, 0);
178
179    re->soft16_engine_image = (SDL_Engine_Image_Entry *) evas_cache_engine_image_engine(re->cache, surface);
180    if (!re->soft16_engine_image)
181      {
182         ERR("Soft16_Image allocation from SDL failed");
183         evas_cache_engine_image_shutdown(re->cache);
184         free(re);
185         return NULL;
186      }
187
188    return re;
189 }
190
191
192 static int
193 evas_engine_sdl16_setup(Evas *e, void *in)
194 {
195    Evas_Engine_Info_SDL_16      *info = (Evas_Engine_Info_SDL_16 *) in;
196
197    if (evas_output_method_get(e) != evas_render_method_lookup("software_16_sdl"))
198      return 0;
199
200    SDL_Init(SDL_INIT_NOPARACHUTE);
201
202    if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
203      {
204         ERR("SDL_Init failed with %s", SDL_GetError());
205         SDL_Quit();
206         return 0;
207      }
208
209    e->engine.data.output = _sdl16_output_setup(e->output.w, e->output.h,
210                                                info->info.rotation,
211                                                info->info.fullscreen,
212                                                info->info.noframe,
213                                                info->info.hwsurface);
214    if (!e->engine.data.output)
215      return 0;
216
217    e->engine.func = &func;
218    e->engine.data.context = e->engine.func->context_new(e->engine.data.output);
219
220    return 1;
221 }
222
223 static void
224 evas_engine_sdl16_output_free(void *data)
225 {
226    Render_Engine *re;
227
228    re = (Render_Engine *)data;
229    if (re->tb) evas_common_tilebuf_free(re->tb);
230    if (re->rects) evas_common_tilebuf_free_render_rects(re->rects);
231    if (re->tmp_out) evas_cache_image_drop(&re->tmp_out->cache_entry);
232    if (re->soft16_engine_image) evas_cache_engine_image_drop(&re->soft16_engine_image->cache_entry);
233    free(re);
234
235    evas_common_font_shutdown();
236    evas_common_image_shutdown();
237    evas_common_soft16_image_shutdown();
238 }
239
240 static void
241 evas_engine_sdl16_output_resize(void *data, int w, int h)
242 {
243    Render_Engine        *re = data;
244    SDL_Surface          *surface;
245
246    if ((re->w == w) && (re->h == h)) return;
247
248    evas_cache_engine_image_drop(&re->soft16_engine_image->cache_entry);
249
250    evas_common_tilebuf_free(re->tb);
251    re->w = w;
252    re->h = h;
253    re->tb = evas_common_tilebuf_new(w, h);
254    if (re->tb)
255      evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE);
256
257    surface = SDL_SetVideoMode(w, h, 16,
258                               (re->flags.hwsurface ? SDL_HWSURFACE : SDL_SWSURFACE)
259                               | (re->flags.fullscreen ? SDL_FULLSCREEN : 0)
260                               | (re->flags.noframe ? SDL_NOFRAME : 0));
261    if (!surface)
262      {
263         ERR("Unable to change the resolution to : %ix%i", w, h);
264         exit(-1);
265      }
266    re->soft16_engine_image = (SDL_Engine_Image_Entry *) evas_cache_engine_image_engine(re->cache, surface);
267    if (!re->soft16_engine_image)
268      {
269         ERR("RGBA_Image allocation from SDL failed");
270         exit(-1);
271      }
272
273    SDL_FillRect(surface, NULL, 0);
274
275    if (re->tmp_out)
276      {
277         evas_cache_image_drop(&re->tmp_out->cache_entry);
278         re->tmp_out = NULL;
279      }
280 }
281
282 static void
283 evas_engine_sdl16_output_tile_size_set(void *data, int w, int h)
284 {
285    Render_Engine *re;
286
287    re = (Render_Engine *)data;
288    evas_common_tilebuf_set_tile_size(re->tb, w, h);
289 }
290
291 static void
292 evas_engine_sdl16_output_redraws_rect_add(void *data, int x, int y, int w, int h)
293 {
294    Render_Engine *re;
295
296    re = (Render_Engine *)data;
297    evas_common_tilebuf_add_redraw(re->tb, x, y, w, h);
298 }
299
300 static void
301 evas_engine_sdl16_output_redraws_rect_del(void *data, int x, int y, int w, int h)
302 {
303    Render_Engine *re;
304
305    re = (Render_Engine *)data;
306    evas_common_tilebuf_del_redraw(re->tb, x, y, w, h);
307 }
308
309 static void
310 evas_engine_sdl16_output_redraws_clear(void *data)
311 {
312    Render_Engine *re;
313
314    re = (Render_Engine *)data;
315    evas_common_tilebuf_clear(re->tb);
316 }
317
318 static void *
319 evas_engine_sdl16_output_redraws_next_update_get(void *data,
320                                                  int *x, int *y, int *w, int *h,
321                                                  int *cx, int *cy, int *cw, int *ch)
322 {
323    Render_Engine        *re = data;
324    Tilebuf_Rect         *tb_rect;
325    SDL_Rect              rect;
326
327    if (re->flags.end)
328      {
329         re->flags.end = 0;
330         return NULL;
331      }
332    if (!re->rects)
333      {
334         re->rects = evas_common_tilebuf_get_render_rects(re->tb);
335         re->cur_rect = re->rects;
336         if (re->rot != 0) _tmp_out_alloc(re); /* grows if required */
337      }
338    if (!re->cur_rect)
339      {
340         if (re->rects) evas_common_tilebuf_free_render_rects(re->rects);
341         re->rects = NULL;
342         return NULL;
343      }
344
345    tb_rect = re->cur_rect;
346    *cx = *x = tb_rect->x;
347    *cy = *y = tb_rect->y;
348    *cw = *w = tb_rect->w;
349    *ch = *h = tb_rect->h;
350    re->cur_rect = (Tilebuf_Rect *)((EINA_INLIST_GET(re->cur_rect))->next);
351    if (!re->cur_rect)
352      {
353         evas_common_tilebuf_free_render_rects(re->rects);
354         re->rects = NULL;
355         re->flags.end = 1;
356      }
357
358    if (re->rot != 0)
359      {
360         *cx = 0;
361         *cy = 0;
362      }
363
364    rect.x = *x;
365    rect.y = *y;
366    rect.w = *w;
367    rect.h = *h;
368
369    /* Return the "fake" surface so it is passed to the drawing routines. */
370    return re->soft16_engine_image;
371 }
372
373 static void
374 _blit_rot_90(Soft16_Image *dst, const Soft16_Image *src,
375              int out_x, int out_y, int w, int h)
376 {
377    DATA16 *dp, *sp;
378    int x, y;
379
380    sp = src->pixels;
381    dp = dst->pixels + (out_x +
382                        (w + out_y - 1) * dst->stride);
383
384    for (y = 0; y < h; y++)
385      {
386         DATA16 *dp_itr, *sp_itr;
387
388         sp_itr = sp;
389         dp_itr = dp;
390
391         for (x = 0; x < w; x++)
392           {
393              *dp_itr = *sp_itr;
394
395              sp_itr++;
396              dp_itr -= dst->stride;
397           }
398         sp += src->stride;
399         dp++;
400      }
401 }
402
403 static void
404 _blit_rot_180(Soft16_Image *dst, const Soft16_Image *src,
405               int out_x, int out_y, int w, int h)
406 {
407    DATA16 *dp, *sp;
408    int x, y;
409
410    sp = src->pixels;
411    dp = dst->pixels + ((w + out_x - 1) +
412                        (h + out_y - 1) * dst->stride);
413
414    for (y = 0; y < h; y++)
415      {
416         DATA16 *dp_itr, *sp_itr;
417
418         sp_itr = sp;
419         dp_itr = dp;
420
421         for (x = 0; x < w; x++)
422           {
423              *dp_itr = *sp_itr;
424
425              sp_itr++;
426              dp_itr--;
427           }
428         sp += src->stride;
429         dp -= dst->stride;
430      }
431 }
432
433 static void
434 _blit_rot_270(Soft16_Image *dst, const Soft16_Image *src,
435               int out_x, int out_y, int w, int h)
436 {
437    DATA16 *dp, *sp;
438    int x, y;
439
440    sp = src->pixels;
441    dp = dst->pixels + ((h + out_x - 1) +
442                        out_y * dst->stride);
443
444    for (y = 0; y < h; y++)
445      {
446         DATA16 *dp_itr, *sp_itr;
447
448         sp_itr = sp;
449         dp_itr = dp;
450
451         for (x = 0; x < w; x++)
452           {
453              *dp_itr = *sp_itr;
454
455              sp_itr++;
456              dp_itr += dst->stride;
457           }
458         sp += src->stride;
459         dp--;
460      }
461 }
462
463 static void
464 _tmp_out_process(Render_Engine *re, int out_x, int out_y, int w, int h)
465 {
466    Soft16_Image *d, *s;
467
468    d = (Soft16_Image *) re->soft16_engine_image->cache_entry.src;
469    s = re->tmp_out;
470
471    if ((w < 1) || (h < 1) ||
472        (out_x >= (int)d->cache_entry.w) || (out_y >= (int)d->cache_entry.h))
473      return;
474
475    if (re->rot == 90)
476      _blit_rot_90(d, s, out_x, out_y, w, h);
477    else if (re->rot == 180)
478      _blit_rot_180(d, s, out_x, out_y, w, h);
479    else if (re->rot == 270)
480      _blit_rot_270(d, s, out_x, out_y, w, h);
481 }
482
483 static void
484 evas_engine_sdl16_output_redraws_next_update_push(void *data, void *surface __UNUSED__,
485                                                   int x, int y, int w, int h)
486 {
487    Render_Engine        *re = data;
488    SDL_Rect              rect;
489
490    if (re->update_rects_count + 1 > re->update_rects_limit)
491      {
492         re->update_rects_limit += 8;
493         re->update_rects = realloc(re->update_rects, sizeof (SDL_Rect) * re->update_rects_limit);
494      }
495
496    rect.x = x;
497    rect.y = y;
498    rect.w = w;
499    rect.h = h;
500
501    switch (re->rot)
502      {
503       case 0:
504          break;
505       case 90:
506          rect.x = y;
507          rect.y = re->w - w - x;
508          rect.w = h;
509          rect.h = w;
510          break;
511       case 180:
512          rect.x = re->w - w - x;
513          rect.y = re->h - h - y;
514          break;
515       case 270:
516          rect.x = re->h - h - y;
517          rect.y = x;
518          rect.w = h;
519          rect.h = w;
520          break;
521       default:
522          abort();
523      }
524
525    re->update_rects[re->update_rects_count] = rect;
526
527    if (re->rot != 0)
528      _tmp_out_process(re, rect.x, rect.y, w, h);
529
530    ++re->update_rects_count;
531 }
532
533 static void
534 evas_engine_sdl16_output_flush(void *data)
535 {
536    Render_Engine        *re = data;
537
538    if (re->update_rects_count > 0)
539      SDL_UpdateRects(re->soft16_engine_image->surface, re->update_rects_count, re->update_rects);
540
541    re->update_rects_count = 0;
542 }
543
544 static void
545 evas_engine_sdl16_output_idle_flush(void *data)
546 {
547    Render_Engine *re;
548
549    re = (Render_Engine *)data;
550    if (re->tmp_out)
551      {
552         evas_cache_image_drop(&re->tmp_out->cache_entry);
553         re->tmp_out = NULL;
554      }
555 }
556
557 static void*
558 evas_engine_sdl16_image_load(void *data, const char *file, const char *key, int *error, Evas_Image_Load_Opts *lo)
559 {
560    Render_Engine*       re = (Render_Engine*) data;;
561
562    *error = 0;
563    return evas_cache_engine_image_request(re->cache, file, key, lo, NULL, error);
564 }
565
566 static int
567 evas_engine_sdl16_image_alpha_get(void *data __UNUSED__, void *image)
568 {
569    SDL_Engine_Image_Entry       *eim = image;
570    Soft16_Image                 *im;
571
572    if (!eim) return 1;
573    im = (Soft16_Image *) eim->cache_entry.src;
574    if (im->cache_entry.flags.alpha) return 1;
575    return 0;
576 }
577
578 static void
579 evas_engine_sdl16_image_size_get(void *data __UNUSED__, void *image, int *w, int *h)
580 {
581    SDL_Engine_Image_Entry       *eim;
582
583    eim = image;
584    if (w) *w = eim->cache_entry.w;
585    if (h) *h = eim->cache_entry.h;
586 }
587
588 static int
589 evas_engine_sdl16_image_colorspace_get(void *data __UNUSED__, void *image __UNUSED__)
590 {
591    return EVAS_COLORSPACE_RGB565_A5P;
592 }
593
594 static void
595 evas_engine_sdl16_image_colorspace_set(void *data __UNUSED__, void *image __UNUSED__, int cspace __UNUSED__)
596 {
597    /* FIXME: Not implemented. */
598 }
599
600 static void*
601 evas_engine_sdl16_image_new_from_copied_data(void *data,
602                                              int w, int h,
603                                              DATA32* image_data,
604                                              int alpha, int cspace)
605 {
606    Render_Engine        *re = data;
607
608    if (cspace != EVAS_COLORSPACE_RGB565_A5P)
609      {
610         WRN("Unsupported colorspace %d in %s() (%s:%d)",
611                 cspace, __FUNCTION__, __FILE__, __LINE__);
612         return NULL;
613      }
614
615    WRN("s image_data: %p", image_data);
616
617    return evas_cache_engine_image_copied_data(re->cache,
618                                               w, h,
619                                               image_data,
620                                               alpha, cspace, NULL);
621 }
622
623 static void*
624 evas_engine_sdl16_image_new_from_data(void *data, int w, int h, DATA32* image_data, int alpha, int cspace)
625 {
626    Render_Engine        *re = data;
627
628    if (cspace != EVAS_COLORSPACE_RGB565_A5P)
629      {
630         WRN("Unsupported colorspace %d in %s() (%s:%d)",
631                 cspace, __FUNCTION__, __FILE__, __LINE__);
632         return NULL;
633      }
634
635    return evas_cache_engine_image_data(re->cache,
636                                        w, h,
637                                        image_data,
638                                        alpha, cspace, NULL);
639 }
640
641 static void
642 evas_engine_sdl16_image_free(void *data __UNUSED__, void *image)
643 {
644    SDL_Engine_Image_Entry       *eim = image;
645
646    evas_cache_engine_image_drop(&eim->cache_entry);
647 }
648
649 static void*
650 evas_engine_sdl16_image_size_set(void *data __UNUSED__, void *image, int w, int h)
651 {
652    SDL_Engine_Image_Entry       *eim = image;
653
654    return evas_cache_engine_image_size_set(&eim->cache_entry, w, h);
655 }
656
657 static void*
658 evas_engine_sdl16_image_dirty_region(void *data __UNUSED__,
659                                      void *image,
660                                      int x, int y, int w, int h)
661 {
662    SDL_Engine_Image_Entry       *eim = image;
663
664    return evas_cache_engine_image_dirty(&eim->cache_entry, x, y, w, h);
665 }
666
667 static void*
668 evas_engine_sdl16_image_data_get(void *data __UNUSED__, void *image,
669                                  int to_write, DATA32** image_data, int *err)
670 {
671    SDL_Engine_Image_Entry       *eim = image;
672    Soft16_Image                 *im;
673    int                           error;
674    
675    if (!eim)
676      {
677         *image_data = NULL;
678         return NULL;
679      }
680    im = (Soft16_Image *) eim->cache_entry.src;
681    error = evas_cache_image_load_data(&im->cache_entry);
682
683    if (to_write)
684      eim = (SDL_Engine_Image_Entry *) evas_cache_engine_image_alone(&eim->cache_entry,
685                                                                     NULL);
686
687    /* FIXME: Handle colorspace conversion correctly. */
688    if (image_data) *image_data = (DATA32 *) im->pixels;
689
690    if (err) *err = error;
691    return eim;
692 }
693
694 static void*
695 evas_engine_sdl16_image_data_put(void *data, void *image, DATA32* image_data)
696 {
697    SDL_Engine_Image_Entry       *eim = image;
698    SDL_Engine_Image_Entry       *eim_new;
699    Render_Engine                *re = data;
700    Soft16_Image                 *im;
701
702    if (!eim) return NULL;
703    im = (Soft16_Image *) eim->cache_entry.src;
704
705    /* FIXME: Handle colorspace conversion correctly. */
706    if ((DATA16 *) image_data == im->pixels) return eim;
707
708    eim_new = (SDL_Engine_Image_Entry *) evas_cache_engine_image_data(re->cache,
709                                                                      eim->cache_entry.w, eim->cache_entry.h,
710                                                                      image_data,
711                                                                      func.image_alpha_get(data, eim),
712                                                                      func.image_colorspace_get(data, eim),
713                                                                      NULL);
714    evas_cache_engine_image_drop(&eim->cache_entry);
715
716    return eim_new;
717 }
718
719 static void
720 evas_engine_sdl16_image_data_preload_request(void *data __UNUSED__, void *image, const void *target)
721 {
722    SDL_Engine_Image_Entry       *eim = image;
723    Soft16_Image                 *im;
724
725    if (!eim) return ;
726    im = (Soft16_Image *) eim->cache_entry.src;
727    if (!im) return ;
728    evas_cache_image_preload_data(&im->cache_entry, target);
729 }
730
731 static void
732 evas_engine_sdl16_image_data_preload_cancel(void *data __UNUSED__, void *image, const void *target)
733 {
734    SDL_Engine_Image_Entry       *eim = image;
735    Soft16_Image                 *im;
736
737    if (!eim) return ;
738    im = (Soft16_Image *) eim->cache_entry.src;
739    if (!im) return ;
740    evas_cache_image_preload_cancel(&im->cache_entry, target);
741 }
742
743 static void*
744 evas_engine_sdl16_image_alpha_set(void *data __UNUSED__, void *image, int has_alpha)
745 {
746    SDL_Engine_Image_Entry       *eim = image;
747    Soft16_Image                 *im;
748
749    if (!eim) return NULL;
750
751    im = (Soft16_Image *) eim->cache_entry.src;
752
753    if (im->cache_entry.flags.alpha == has_alpha) return eim;
754
755    eim = (SDL_Engine_Image_Entry *) evas_cache_engine_image_alone(&eim->cache_entry,
756                                                                   NULL);
757
758    im = (Soft16_Image *) eim->cache_entry.src;
759
760    im->cache_entry.flags.alpha = has_alpha;
761    eim = (SDL_Engine_Image_Entry *) evas_cache_engine_image_dirty(&eim->cache_entry, 0, 0, eim->cache_entry.w, eim->cache_entry.h);
762
763    return eim;
764 }
765
766 static void*
767 evas_engine_sdl16_image_border_set(void *data __UNUSED__, void *image, int l __UNUSED__, int r __UNUSED__, int t __UNUSED__, int b __UNUSED__)
768 {
769    return image;
770 }
771
772 static void
773 evas_engine_sdl16_image_border_get(void *data __UNUSED__, void *image __UNUSED__, int *l __UNUSED__, int *r __UNUSED__, int *t __UNUSED__, int *b __UNUSED__)
774 {
775    /* FIXME: need to know what evas expect from this call */
776 }
777
778 static void
779 evas_engine_sdl16_image_draw(void *data __UNUSED__, void *context, void *surface, void *image,
780                              int src_region_x, int src_region_y, int src_region_w, int src_region_h,
781                              int dst_region_x, int dst_region_y, int dst_region_w, int dst_region_h,
782                              int smooth)
783 {
784    SDL_Engine_Image_Entry       *eim = image;
785    SDL_Engine_Image_Entry       *dst = surface;
786    int                           mustlock_im = 0;
787    int                           mustlock_dst = 0;
788
789    evas_cache_engine_image_load_data(&eim->cache_entry);
790
791    /* Fallback to software method */
792    if (SDL_MUSTLOCK(dst->surface))
793      {
794         mustlock_dst = 1;
795         SDL_LockSurface(dst->surface);
796         _SDL_UPDATE_PIXELS(dst);
797      }
798
799    if (eim->surface && SDL_MUSTLOCK(eim->surface))
800      {
801         mustlock_im = 1;
802         SDL_LockSurface(eim->surface);
803         _SDL_UPDATE_PIXELS(eim);
804      }
805
806    evas_common_soft16_image_draw((Soft16_Image *) eim->cache_entry.src,
807                      (Soft16_Image *) dst->cache_entry.src,
808                      context,
809                      src_region_x, src_region_y, src_region_w, src_region_h,
810                      dst_region_x, dst_region_y, dst_region_w, dst_region_h,
811                      smooth);
812
813    if (mustlock_im)
814      SDL_UnlockSurface(eim->surface);
815
816    if (mustlock_dst)
817      SDL_UnlockSurface(dst->surface);
818 }
819
820 static void
821 evas_engine_sdl16_image_map_draw(void *data __UNUSED__, void *context __UNUSED__, void *surface __UNUSED__, void *image __UNUSED__, int npoints __UNUSED__, RGBA_Map_Point *p __UNUSED__, int smooth __UNUSED__, int level __UNUSED__)
822 {
823 }
824
825 static void
826 evas_engine_sdl16_image_scale_hint_set(void *data __UNUSED__, void *image __UNUSED__, int hint __UNUSED__)
827 {
828 }
829
830 static int
831 evas_engine_sdl16_image_scale_hint_get(void *data __UNUSED__, void *image __UNUSED__)
832 {
833    return EVAS_IMAGE_SCALE_HINT_NONE;
834 }
835
836
837 static void
838 evas_engine_sdl16_image_cache_flush(void *data)
839 {
840    Render_Engine        *re = (Render_Engine*) data;
841    int                   size;
842
843    size = evas_cache_engine_image_get(re->cache);
844    evas_cache_engine_image_set(re->cache, 0);
845    evas_cache_engine_image_set(re->cache, size);
846 }
847
848 static void
849 evas_engine_sdl16_image_cache_set(void *data, int bytes)
850 {
851    Render_Engine        *re = (Render_Engine*) data;
852
853    evas_cache_engine_image_set(re->cache, bytes);
854 }
855
856 static int
857 evas_engine_sdl16_image_cache_get(void *data)
858 {
859    Render_Engine        *re = (Render_Engine*) data;
860
861    return evas_cache_engine_image_get(re->cache);
862 }
863
864 static char*
865 evas_engine_sdl16_image_comment_get(void *data __UNUSED__, void *image __UNUSED__, char *key __UNUSED__)
866 {
867    return NULL;
868 }
869
870 static char*
871 evas_engine_sdl16_image_format_get(void *data __UNUSED__, void *image __UNUSED__)
872 {
873    /* FIXME: need to know what evas expect from this call */
874    return NULL;
875 }
876
877 static void
878 evas_engine_sdl16_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Evas_Text_Props *intl_props)
879 {
880    static RGBA_Image            *im = NULL;
881    SDL_Engine_Image_Entry       *eim = surface;
882    Soft16_Image                 *dst = (Soft16_Image *) eim->cache_entry.src;
883    int                           mustlock_im = 0;
884
885    if (!im)
886      im = (RGBA_Image *) evas_cache_image_empty(evas_common_image_cache_get());
887    evas_cache_image_surface_alloc(&im->cache_entry, dst->cache_entry.w, dst->cache_entry.h);
888
889    if (eim->surface && SDL_MUSTLOCK(eim->surface))
890      {
891         mustlock_im = 1;
892         SDL_LockSurface(eim->surface);
893         _SDL_UPDATE_PIXELS(eim);
894      }
895    evas_common_draw_context_font_ext_set(context,
896                                          dst,
897                                          evas_common_soft16_font_glyph_new,
898                                          evas_common_soft16_font_glyph_free,
899                                          evas_common_soft16_font_glyph_draw);
900    evas_common_font_draw(im, context, font, x, y, intl_props);
901    evas_common_draw_context_font_ext_set(context,
902                                          NULL,
903                                          NULL,
904                                          NULL,
905                                          NULL);
906
907    if (mustlock_im)
908      SDL_UnlockSurface(eim->surface);
909 }
910
911 static void
912 evas_engine_sdl16_line_draw(void *data __UNUSED__, void *context, void *surface, int x1, int y1, int x2, int y2)
913 {
914    SDL_Engine_Image_Entry       *eim = surface;
915    int                           mustlock_im = 0;
916
917    if (eim->surface && SDL_MUSTLOCK(eim->surface))
918      {
919         mustlock_im = 1;
920         SDL_LockSurface(eim->surface);
921         _SDL_UPDATE_PIXELS(eim);
922      }
923
924    evas_common_soft16_line_draw((Soft16_Image *) eim->cache_entry.src,
925                     context,
926                     x1, y1, x2, y2);
927
928    if (mustlock_im)
929      SDL_UnlockSurface(eim->surface);
930 }
931
932 static void
933 evas_engine_sdl16_rectangle_draw(void *data __UNUSED__, void *context, void *surface, int x, int y, int w, int h)
934 {
935    SDL_Engine_Image_Entry       *eim = surface;
936 #if ENGINE_SDL_PRIMITIVE
937    RGBA_Draw_Context            *dc = context;
938 #endif
939    Soft16_Image                 *im;
940    int                           mustlock_im = 0;
941
942 #if ENGINE_SDL_PRIMITIVE
943    if (A_VAL(&dc->col.col) != 0x00)
944      {
945         if (A_VAL(&dc->col.col) != 0xFF)
946           {
947 #endif
948              if (eim->surface && SDL_MUSTLOCK(eim->surface))
949                {
950                   mustlock_im = 1;
951                   SDL_LockSurface(eim->surface);
952                   _SDL_UPDATE_PIXELS(eim);
953                }
954
955              im = (Soft16_Image *) eim->cache_entry.src;
956
957              evas_common_soft16_rectangle_draw(im, context, x, y, w, h);
958
959              if (mustlock_im)
960                SDL_UnlockSurface(eim->surface);
961 #if ENGINE_SDL_PRIMITIVE
962           }
963         else
964           {
965              SDL_Rect        dstrect;
966
967              if (dc->clip.use)
968                {
969                   SDL_Rect   cliprect;
970
971                   cliprect.x = dc->clip.x;
972                   cliprect.y = dc->clip.y;
973                   cliprect.w = dc->clip.w;
974                   cliprect.h = dc->clip.h;
975
976                   SDL_SetClipRect(eim->surface, &cliprect);
977                }
978
979              dstrect.x = x;
980              dstrect.y = y;
981              dstrect.w = w;
982              dstrect.h = h;
983
984              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));
985
986              if (dc->clip.use)
987                SDL_SetClipRect(eim->surface, NULL);
988           }
989      }
990 #endif
991 }
992
993 static void
994 evas_engine_sdl16_polygon_draw(void *data __UNUSED__, void *context, void *surface, void *polygon, int x, int y)
995 {
996    SDL_Engine_Image_Entry       *eim = surface;
997    int                           mustlock_im = 0;
998
999    if (eim->surface && SDL_MUSTLOCK(eim->surface))
1000      {
1001         mustlock_im = 1;
1002         SDL_LockSurface(eim->surface);
1003         _SDL_UPDATE_PIXELS(eim);
1004      }
1005
1006    evas_common_soft16_polygon_draw((Soft16_Image *) eim->cache_entry.src, context, polygon, x, y);
1007
1008    if (mustlock_im)
1009      SDL_UnlockSurface(eim->surface);
1010 }
1011
1012 static void
1013 evas_engine_sdl16_image_stride_get(void *data __UNUSED__, void *image, int *stride)
1014 {
1015    SDL_Engine_Image_Entry       *eim = image;
1016
1017    if (stride) *stride = 0;
1018    if (!image) return;
1019    if (stride) *stride = ((Soft16_Image*) eim->cache_entry.src)->stride;
1020 }
1021
1022 static Eina_Bool
1023 evas_engine_sdl16_canvas_alpha_get(void *data __UNUSED__, void *context __UNUSED__)
1024 {
1025    return EINA_FALSE;
1026 }
1027
1028 /* module advertising code */
1029 static int
1030 module_open(Evas_Module *em)
1031 {
1032    if (!em) return 0;
1033    /* get whatever engine module we inherit from */
1034    if (!_evas_module_engine_inherit(&pfunc, "software_16")) return 0;
1035    _evas_engine_soft16_sdl_log_dom = eina_log_domain_register
1036      ("evas-software_16_sdl", EVAS_DEFAULT_LOG_COLOR);
1037    if (_evas_engine_soft16_sdl_log_dom < 0)
1038      {
1039         EINA_LOG_ERR("Can not create a module log domain.");
1040         return 0;
1041      }
1042
1043    /* store it for later use */
1044    func = pfunc;
1045    /* now to override methods */
1046 #define ORD(f) EVAS_API_OVERRIDE(f, &func, evas_engine_sdl16_)
1047    ORD(info);
1048    ORD(info_free);
1049    ORD(setup);
1050    ORD(canvas_alpha_get);
1051    ORD(output_free);
1052    ORD(output_resize);
1053    ORD(output_tile_size_set);
1054    ORD(output_redraws_rect_add);
1055    ORD(output_redraws_rect_del);
1056    ORD(output_redraws_clear);
1057    ORD(output_redraws_next_update_get);
1058    ORD(output_redraws_next_update_push);
1059    ORD(output_flush);
1060    ORD(output_idle_flush);
1061    ORD(image_load);
1062    ORD(image_alpha_get);
1063    ORD(image_size_get);
1064    ORD(image_colorspace_get);
1065    ORD(image_colorspace_set);
1066    ORD(image_new_from_copied_data);
1067    ORD(image_new_from_data);
1068    ORD(image_free);
1069    ORD(image_size_set);
1070    ORD(image_dirty_region);
1071    ORD(image_data_get);
1072    ORD(image_data_put);
1073    ORD(image_data_preload_request);
1074    ORD(image_data_preload_cancel);
1075    ORD(image_alpha_set);
1076    ORD(image_border_set);
1077    ORD(image_border_get);
1078    ORD(image_draw);
1079    ORD(image_map_draw);
1080    ORD(image_cache_flush);
1081    ORD(image_cache_set);
1082    ORD(image_cache_get);
1083    ORD(image_comment_get);
1084    ORD(image_format_get);
1085    ORD(image_stride_get);
1086    ORD(font_draw);
1087    ORD(line_draw);
1088    ORD(rectangle_draw);
1089    ORD(polygon_draw);
1090    
1091    ORD(image_scale_hint_set);
1092    ORD(image_scale_hint_get);
1093    
1094    /* now advertise out own api */
1095    em->functions = (void *)(&func);
1096    return 1;
1097 }
1098
1099 static void
1100 module_close(Evas_Module *em __UNUSED__)
1101 {
1102   eina_log_domain_unregister(_evas_engine_soft16_sdl_log_dom);
1103 }
1104
1105 static Evas_Module_Api evas_modapi =
1106 {
1107    EVAS_MODULE_API_VERSION,
1108    "software_16_sdl",
1109    "none",
1110    {
1111      module_open,
1112      module_close
1113    }
1114 };
1115
1116 EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_ENGINE, engine, software_16_sdl);
1117
1118 #ifndef EVAS_STATIC_BUILD_SOFTWARE_SDL
1119 EVAS_EINA_MODULE_DEFINE(engine, software_16_sdl);
1120 #endif
1121
1122 static Engine_Image_Entry*
1123 _sdl16_image_alloc(void)
1124 {
1125    SDL_Engine_Image_Entry       *new;
1126
1127    new = calloc(1, sizeof (SDL_Engine_Image_Entry));
1128
1129    return (Engine_Image_Entry *) new;
1130 }
1131
1132 static void
1133 _sdl16_image_delete(Engine_Image_Entry *eim)
1134 {
1135    free(eim);
1136 }
1137
1138 static int
1139 _sdl16_image_constructor(Engine_Image_Entry *ie, void* data __UNUSED__)
1140 {
1141    SDL_Surface                  *sdl = NULL;
1142    SDL_Engine_Image_Entry       *eim = (SDL_Engine_Image_Entry *) ie;
1143    Soft16_Image                 *im;
1144
1145    im = (Soft16_Image *) ie->src;
1146
1147    if (im->pixels)
1148      {
1149         /* FIXME: Take care of CSPACE */
1150         sdl = SDL_CreateRGBSurfaceFrom(im->pixels,
1151                                        ie->w, ie->h,
1152                                        16, ie->w * 2,
1153                                        RMASK565, GMASK565, BMASK565, AMASK565);
1154         eim->surface = sdl;
1155         eim->flags.engine_surface = 0;
1156      }
1157
1158    return EVAS_LOAD_ERROR_NONE;
1159 }
1160
1161 static void
1162 _sdl16_image_destructor(Engine_Image_Entry *eim)
1163 {
1164    SDL_Engine_Image_Entry       *seie = (SDL_Engine_Image_Entry *) eim;
1165
1166    if (seie->surface && !seie->flags.engine_surface)
1167      SDL_FreeSurface(seie->surface);
1168    seie->surface = NULL;
1169 }
1170
1171 static void
1172 _sdl16_image_dirty_region(Engine_Image_Entry *eim, unsigned int x, unsigned int y, unsigned int w, unsigned int h)
1173 {
1174    SDL_Engine_Image_Entry       *dst;
1175    RGBA_Image *im;
1176
1177    dst = (SDL_Engine_Image_Entry *) eim;
1178
1179    SDL_UpdateRect(dst->surface, x, y, w, h);
1180
1181    im = (RGBA_Image *)eim->src;
1182    im->flags |= RGBA_IMAGE_IS_DIRTY;
1183 }
1184
1185 static int
1186 _sdl16_image_dirty(Engine_Image_Entry *dst, const Engine_Image_Entry *src __UNUSED__)
1187 {
1188    SDL_Engine_Image_Entry       *eim = (SDL_Engine_Image_Entry *) dst;
1189    SDL_Surface                  *sdl = NULL;
1190    Soft16_Image                 *im;
1191
1192    im = (Soft16_Image *) dst->src;
1193
1194    /* FIXME: Take care of CSPACE */
1195    sdl = SDL_CreateRGBSurfaceFrom(im->pixels,
1196                                   dst->w, dst->h,
1197                                   16, dst->w * 2,
1198                                   RMASK565, GMASK565, BMASK565, AMASK565);
1199    eim->surface = sdl;
1200    eim->flags.engine_surface = 0;
1201
1202    return 0;
1203 }
1204
1205 static int
1206 _sdl16_image_size_set(Engine_Image_Entry *dst, const Engine_Image_Entry *src __UNUSED__)
1207 {
1208    SDL_Engine_Image_Entry       *eim = (SDL_Engine_Image_Entry *) dst;
1209    SDL_Surface                  *sdl;
1210    Soft16_Image                 *im;
1211
1212    im = (Soft16_Image *) dst->src;
1213
1214    /* FIXME: handle im == NULL */
1215    sdl = SDL_CreateRGBSurfaceFrom(im->pixels,
1216                                   dst->w, dst->h,
1217                                   16, dst->w * 2,
1218                                   RMASK565, GMASK565, BMASK565, AMASK565);
1219
1220    eim->surface = sdl;
1221
1222    return 0;
1223 }
1224
1225 static int
1226 _sdl16_image_update_data(Engine_Image_Entry* dst, void* engine_data)
1227 {
1228    SDL_Engine_Image_Entry       *eim = (SDL_Engine_Image_Entry *) dst;
1229    SDL_Surface                  *sdl = NULL;
1230    Soft16_Image                 *im;
1231
1232    im = (Soft16_Image *) dst->src;
1233
1234    if (engine_data)
1235      {
1236         sdl = engine_data;
1237
1238         if (im)
1239           {
1240              im->pixels = sdl->pixels;
1241              im->stride = sdl->pitch / 2;
1242              im->flags.free_pixels = 0;
1243 /*              im->alpha = calloc(1, sizeof (DATA8) * _calc_stride(sdl->w) * sdl->h); */
1244 /*              im->flags.free_alpha = 0; */
1245 /*              im->flags.have_alpha = 1; */
1246              im->alpha = NULL;
1247              im->flags.free_alpha = 0;
1248              im->cache_entry.flags.alpha = 0;
1249
1250              dst->src->w = sdl->w;
1251              dst->src->h = sdl->h;
1252           }
1253         dst->w = sdl->w;
1254         dst->h = sdl->h;
1255      }
1256    else
1257      {
1258         SDL_FreeSurface(eim->surface);
1259         /* FIXME: Take care of CSPACE */
1260         sdl = SDL_CreateRGBSurfaceFrom(im->pixels,
1261                                        dst->w, dst->h,
1262                                        16, dst->w * 2,
1263                                        RMASK565, GMASK565, BMASK565, AMASK565);
1264      }
1265
1266    eim->surface = sdl;
1267
1268    return 0;
1269 }
1270
1271 static void
1272 _sdl16_image_load(Engine_Image_Entry *eim, const Image_Entry* ie_im)
1273 {
1274    SDL_Engine_Image_Entry       *load = (SDL_Engine_Image_Entry *) eim;
1275    SDL_Surface                  *sdl;
1276
1277    if (!load->surface)
1278      {
1279         Soft16_Image            *im;
1280
1281         im = (Soft16_Image *) ie_im;
1282
1283         sdl = SDL_CreateRGBSurfaceFrom(im->pixels,
1284                                        eim->w, eim->h,
1285                                        16, eim->w * 2,
1286                                        RMASK565, GMASK565, BMASK565, AMASK565);
1287         load->surface = sdl;
1288      }
1289 }
1290
1291 static int
1292 _sdl16_image_mem_size_get(Engine_Image_Entry *eim)
1293 {
1294    SDL_Engine_Image_Entry       *seie = (SDL_Engine_Image_Entry *) eim;
1295    int                           size = 0;
1296
1297    /* FIXME: Count surface size. */
1298    if (seie->surface)
1299      size = sizeof (SDL_Surface) + sizeof (SDL_PixelFormat);
1300
1301    return size;
1302 }
1303
1304 #ifdef DEBUG_SDL
1305 static void
1306 _sdl16_image_debug(const char* context, Engine_Image_Entry* im)
1307 {
1308 }
1309 #endif