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