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