aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/evas/src/modules/engines/directfb/evas_engine.c
diff options
context:
space:
mode:
authorDavid Walter Seikel2012-01-04 18:41:13 +1000
committerDavid Walter Seikel2012-01-04 18:41:13 +1000
commitdd7595a3475407a7fa96a97393bae8c5220e8762 (patch)
treee341e911d7eb911a51684a7412ef7f7c7605d28e /libraries/evas/src/modules/engines/directfb/evas_engine.c
parentAdd the skeleton. (diff)
downloadSledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.zip
SledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.tar.gz
SledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.tar.bz2
SledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.tar.xz
Add the base Enlightenment Foundation Libraries - eina, eet, evas, ecore, embryo, and edje.
Note that embryo wont be used, but I'm not sure yet if you can build edje without it.
Diffstat (limited to 'libraries/evas/src/modules/engines/directfb/evas_engine.c')
-rw-r--r--libraries/evas/src/modules/engines/directfb/evas_engine.c1753
1 files changed, 1753 insertions, 0 deletions
diff --git a/libraries/evas/src/modules/engines/directfb/evas_engine.c b/libraries/evas/src/modules/engines/directfb/evas_engine.c
new file mode 100644
index 0000000..17914ab
--- /dev/null
+++ b/libraries/evas/src/modules/engines/directfb/evas_engine.c
@@ -0,0 +1,1753 @@
1#include <assert.h>
2#include <math.h>
3#include <string.h>
4#include <sys/time.h>
5#include <time.h>
6#include "evas_engine.h"
7#include "evas_common.h" /* Also includes international specific stuff */
8
9/* Uses Evas own image_draw primitive, for comparison purposes only. */
10//#define DFB_USE_EVAS_IMAGE_DRAW 1
11//#define DFB_USE_EVAS_RECT_DRAW 1
12//#define DFB_USE_EVAS_POLYGON_DRAW 1
13//#define DFB_UPDATE_INDIVIDUAL_RECTS 1
14#define DFB_FLIP_FLAGS DSFLIP_NONE
15//#define DFB_FLIP_FLAGS (DSFLIP_ONSYNC | DSFLIP_WAIT)
16
17/* Turn on debug */
18//#define DFB_DEBUG_IMAGE 1
19//#define DFB_DEBUG_FLAGS 1
20//#define DFB_DEBUG_ACCELERATION 1
21int _evas_engine_directfb_log_dom = -1;
22
23static Evas_Func func = {};
24static Evas_Func parent_func = {};
25static IDirectFB *dfb = NULL; /* XXX HACK to work around evas image cache
26 * lack of extra data. Fix it instead later.
27 */
28
29
30/***********************************************************************
31 * Evas helpers
32 **********************************************************************/
33static void
34_context_get_color(RGBA_Draw_Context *dc, int *r, int *g, int *b, int *a)
35{
36 DATA32 col;
37
38 if (dc->mul.use)
39 col = dc->mul.col;
40 else
41 col = dc->col.col;
42
43 *r = R_VAL(&col);
44 *g = G_VAL(&col);
45 *b = B_VAL(&col);
46 *a = A_VAL(&col);
47}
48
49
50/***********************************************************************
51 * DirectFB helpers
52 **********************************************************************/
53static void
54_dfb_surface_clear(IDirectFBSurface *surface, int x, int y, int w, int h)
55{
56 DFBRegion cr;
57 DFBResult r;
58
59 cr.x1 = x;
60 cr.y1 = y;
61 cr.x2 = x + w - 1;
62 cr.y2 = y + h - 1;
63 r = surface->SetClip(surface, &cr);
64 if (r != DFB_OK)
65 goto error;
66
67 r = surface->Clear(surface, 0, 0, 0, 0);
68 if (r != DFB_OK)
69 goto error;
70
71 return;
72
73 error:
74 ERR("DirectFB: could not clear surface: %s",
75 DirectFBErrorString(r));
76}
77
78static void
79_image_clear(DirectFB_Engine_Image_Entry *image, int x, int y, int w, int h)
80{
81 if (image->cache_entry.src->flags.alpha)
82 _dfb_surface_clear(image->surface, x, y, w, h);
83}
84
85static void
86_image_autoset_alpha(DirectFB_Engine_Image_Entry *image)
87{
88 DFBResult r;
89 DFBSurfacePixelFormat fmt;
90 IDirectFBSurface *surface;
91 RGBA_Image *im;
92 int has_alpha;
93
94 surface = image->surface;
95 r = surface->GetPixelFormat(surface, &fmt);
96 if (r != DFB_OK)
97 {
98 ERR("Could not get pixel format: %s",
99 DirectFBErrorString(r));
100 return;
101 }
102
103 /* XXX: check this in more depth in future, if other PF are supported */
104 image->cache_entry.src->flags.alpha = (fmt == DSPF_ARGB);
105}
106
107static void
108_dfb_surface_update(IDirectFBSurface *surface, int x, int y, int w, int h)
109{
110 DFBRegion cr;
111 DFBResult r;
112
113 cr.x1 = x;
114 cr.y1 = y;
115 cr.x2 = x + w - 1;
116 cr.y2 = y + h - 1;
117 r = surface->Flip(surface, &cr, DSFLIP_NONE);
118 if (r != DFB_OK)
119 WRN("Could not update surface: %s",
120 DirectFBErrorString(r));
121}
122
123static IDirectFBSurface *
124_dfb_surface_from_data(IDirectFB *dfb, int w, int h, void *data)
125{
126 IDirectFBSurface *s;
127 DFBSurfaceDescription desc;
128 DFBResult r;
129
130 desc.flags = (DSDESC_CAPS | DSDESC_WIDTH | DSDESC_HEIGHT |
131 DSDESC_PIXELFORMAT | DSDESC_PREALLOCATED);
132 desc.caps = DSCAPS_PREMULTIPLIED;
133 desc.width = w;
134 desc.height = h;
135 desc.preallocated[0].data = data;
136 desc.preallocated[0].pitch = w * 4;
137 desc.preallocated[1].data = NULL;
138 desc.preallocated[1].pitch = 0;
139 desc.pixelformat = DSPF_ARGB;
140 r = dfb->CreateSurface(dfb, &desc, &s);
141 if (r != DFB_OK)
142 {
143 ERR("Cannot create DirectFB surface: %s",
144 DirectFBErrorString(r));
145 return NULL;
146 }
147
148 s->SetPorterDuff(s, DSPD_SRC_OVER);
149
150 return s;
151}
152
153static void
154_dfb_surface_free(IDirectFBSurface *surface)
155{
156 if (surface)
157 surface->Release(surface);
158}
159
160static void
161_dfb_blit_accel_caps_print(IDirectFBSurface *dst, IDirectFBSurface *src)
162{
163#ifdef DFB_DEBUG_ACCELERATION
164 DFBAccelerationMask mask;
165 DFBResult r;
166
167 r = dst->GetAccelerationMask(dst, src, &mask);
168 if (r != DFB_OK)
169 {
170 ERR("Could not retrieve acceleration mask: %s",
171 DirectFBErrorString(r));
172 return;
173 }
174
175 DBG("Acceleration: ");
176
177#define O(m) if (mask & m) DBG(#m " ")
178 O(DFXL_FILLRECTANGLE);
179 O(DFXL_DRAWRECTANGLE);
180 O(DFXL_DRAWLINE);
181 O(DFXL_FILLTRIANGLE);
182 O(DFXL_BLIT);
183 O(DFXL_STRETCHBLIT);
184 O(DFXL_TEXTRIANGLES);
185 O(DFXL_DRAWSTRING);
186#undef O
187
188 if (mask == DFXL_NONE) DBG("<NONE>");
189#endif /* DFB_DEBUG_ACCELERATION */
190}
191
192#ifdef DFB_DEBUG_FLAGS
193static const char *
194_dfb_blit_flags_str(DFBSurfaceBlittingFlags flags)
195{
196 static char buf[1024];
197
198 buf[0] = 0;
199
200#define T(m, n) \
201 do { \
202 if (flags & m) { \
203 if (buf[0] != 0) strcat(buf, " | "); \
204 strcat(buf, n); \
205 } \
206 } while (0)
207
208 T(DSBLIT_BLEND_ALPHACHANNEL, "BLEND_ALPHACHANNEL");
209 T(DSBLIT_BLEND_COLORALPHA, "BLEND_COLORALPHA");
210 T(DSBLIT_COLORIZE, "COLORIZE");
211 T(DSBLIT_SRC_COLORKEY, "SRC_COLORKEY");
212 T(DSBLIT_DST_COLORKEY, "DST_COLORKEY");
213 T(DSBLIT_SRC_PREMULTIPLY, "SRC_PREMULTIPLY");
214 T(DSBLIT_DST_PREMULTIPLY, "DST_PREMULTIPLY");
215 T(DSBLIT_DEMULTIPLY, "DEMULTIPLY");
216 T(DSBLIT_DEINTERLACE, "DSBLIT_DEINTERLACE");
217 T(DSBLIT_SRC_PREMULTCOLOR, "SRC_PREMULTCOLOR");
218 T(DSBLIT_XOR, "XOR");
219 T(DSBLIT_INDEX_TRANSLATION, "INDEX_TRANSLATION");
220#undef T
221
222 if (buf[0] == 0)
223 strcpy(buf, "NOFX");
224
225 return buf;
226}
227
228static const char *
229_dfb_draw_flags_str(DFBSurfaceDrawingFlags flags)
230{
231 static char buf[1024];
232
233 buf[0] = 0;
234
235#define T(m, n) \
236 do { \
237 if (flags & m) { \
238 if (buf[0] != 0) strcat(buf, " | "); \
239 strcat(buf, n); \
240 } \
241 } while (0)
242 T(DSDRAW_BLEND, "BLEND");
243 T(DSDRAW_DST_COLORKEY, "DST_COLORKEY");
244 T(DSDRAW_SRC_PREMULTIPLY, "SRC_PREMULTIPLY");
245 T(DSDRAW_DST_PREMULTIPLY, "DST_PREMULTIPLY");
246 T(DSDRAW_DEMULTIPLY, "DEMULTIPLY");
247 T(DSDRAW_XOR, "DSDRAW_XOR");
248#undef T
249 if (buf[0] == 0)
250 strcpy(buf, "NOFX");
251
252 return buf;
253}
254
255static const char *
256_dfb_blend_func_str(DFBSurfaceBlendFunction func)
257{
258 static char *names[] = {
259 "ZERO",
260 "ONE",
261 "SRCCOLOR",
262 "INVSRCCOLOR",
263 "SRCALPHA",
264 "INVSRCALPHA",
265 "DESTALPHA",
266 "INVDESTALPHA",
267 "DESTCOLOR",
268 "INVDESTCOLOR",
269 "SRCALPHASAT"
270 };
271 func--;
272 if ((func >= 0) && (func <= sizeof(names)/sizeof(*names)))
273 return names[func];
274 else
275 return NULL;
276}
277#endif /* DFB_DEBUG_FLAGS */
278
279int
280_dfb_surface_set_color_from_context(IDirectFBSurface *surface, RGBA_Draw_Context *dc)
281{
282 DFBSurfaceDrawingFlags flags;
283 int r, g, b, a;
284 DFBResult res;
285
286 _context_get_color(dc, &r, &g, &b, &a);
287 if (a == 0)
288 return 0;
289
290 r = 0xff * r / a;
291 g = 0xff * g / a;
292 b = 0xff * b / a;
293
294 res = surface->SetColor(surface, r, g, b, a);
295 if (res != DFB_OK)
296 goto error;
297
298 flags = (a != 255) ? DSDRAW_BLEND : DSDRAW_NOFX;
299 res = surface->SetDrawingFlags(surface, flags);
300 if (res != DFB_OK)
301 goto error;
302
303#ifdef DFB_DEBUG_FLAGS
304 DBG("Color=%d %d %d %d, flags=%s",
305 r, g, b, a, _dfb_draw_flags_str(flags));
306#endif /* DFB_DEBUG_FLAGS */
307
308 return 1;
309
310 error:
311 ERR("Could not set color from context: %s",
312 DirectFBErrorString(res));
313 return 0;
314}
315
316static int
317_dfb_surface_set_blit_params(DirectFB_Engine_Image_Entry *d, DirectFB_Engine_Image_Entry *s, RGBA_Draw_Context *dc)
318{
319 IDirectFBSurface *surface;
320 DFBSurfaceBlittingFlags blit_flags = DSBLIT_NOFX;
321 DFBResult res;
322 int r, g, b, a;
323
324 _context_get_color(dc, &r, &g, &b, &a);
325 if (a == 0)
326 return 0;
327
328 if (a != 255)
329 blit_flags = DSBLIT_BLEND_COLORALPHA | DSBLIT_SRC_PREMULTCOLOR;
330
331 if ((r != a) || (g != a) || (b != a))
332 {
333 blit_flags |= DSBLIT_COLORIZE;
334
335 r = 0xff * r / a;
336 g = 0xff * g / a;
337 b = 0xff * b / a;
338 }
339
340 if (s->cache_entry.src->flags.alpha)
341 blit_flags |= DSBLIT_BLEND_ALPHACHANNEL;
342
343 surface = d->surface;
344
345 if (blit_flags &
346 (DSBLIT_BLEND_COLORALPHA | DSBLIT_SRC_PREMULTCOLOR | DSBLIT_COLORIZE))
347 {
348 res = surface->SetColor(surface, r, g, b, a);
349 if (res != DFB_OK)
350 goto error;
351 }
352
353 res = surface->SetBlittingFlags(surface, blit_flags);
354 if (res != DFB_OK)
355 goto error;
356
357#ifdef DFB_DEBUG_FLAGS
358 DBG("sfunc=%s, dfunc=%s, color=%d %d %d %d, blit=%s, draw=%s",
359 _dfb_blend_func_str(src_func), _dfb_blend_func_str(dst_func),
360 r, g, b, a,
361 _dfb_blit_flags_str(blit_flags), _dfb_draw_flags_str(draw_flags));
362#endif /* DFB_DEBUG_FLAGS */
363
364 return 1;
365
366 error:
367 ERR("Could not set blit params: %s",
368 DirectFBErrorString(res));
369 return 0;
370}
371
372static int
373_dfb_lock_and_sync_image(IDirectFBSurface *surface, RGBA_Image *image, DFBSurfaceLockFlags flags)
374{
375 DFBResult r;
376 int pitch, sw, sh;
377 void *pixels;
378
379 r = surface->GetSize(surface, &sw, &sh);
380 if (r != DFB_OK)
381 return 0;
382
383 r = surface->Lock(surface, flags, &pixels, &pitch);
384 if (r != DFB_OK)
385 return 0;
386
387 if (pitch != (sw * 4))
388 {
389 /* XXX TODO: support other pixel formats. */
390 ERR("IDirectFBSurface pitch(%d) is not supported: "
391 "should be %d.",
392 pitch, sw * 4);
393 surface->Unlock(surface);
394 return 0;
395 }
396
397 image->cache_entry.w = sw;
398 image->cache_entry.h = sh;
399 image->image.data = pixels;
400 return 1;
401}
402
403typedef void (*_cb_for_each_cutout_t)(IDirectFBSurface *surface, RGBA_Draw_Context *dc, const DFBRegion *region, void *data);
404static void
405_dfb_surface_for_each_cutout(IDirectFBSurface *surface, RGBA_Draw_Context *dc, _cb_for_each_cutout_t cb, void *data)
406{
407 Cutout_Rects *rects;
408 int i;
409
410 rects = evas_common_draw_context_apply_cutouts(dc);
411 if (!rects)
412 {
413 DFBRegion cr;
414 cr.x1 = 0;
415 cr.y1 = 0;
416 surface->GetSize(surface, &cr.x2, &cr.y2);
417 cr.x2 -= 1;
418 cr.y2 -= 1;
419 surface->SetClip(surface, NULL);
420 cb(surface, dc, &cr, data);
421 return;
422 }
423
424 for (i = 0; i < rects->active; ++i)
425 {
426 Cutout_Rect *r;
427 DFBRegion cr;
428
429 r = rects->rects + i;
430
431 cr.x1 = r->x;
432 cr.y1 = r->y;
433 cr.x2 = r->x + r->w - 1;
434 cr.y2 = r->y + r->h - 1;
435 surface->SetClip(surface, &cr);
436 cb(surface, dc, &cr, data);
437 }
438 evas_common_draw_context_apply_clear_cutouts(rects);
439}
440
441static void
442_dfb_rect_set(DFBRectangle *r, int x, int y, int w, int h)
443{
444 r->x = x;
445 r->y = y;
446 r->w = w;
447 r->h = h;
448}
449
450
451/***********************************************************************
452 * Image Cache
453 **********************************************************************/
454static Engine_Image_Entry *
455evas_cache_image_dfb_alloc(void)
456{
457 DirectFB_Engine_Image_Entry *deie;
458
459 deie = calloc(1, sizeof (DirectFB_Engine_Image_Entry));
460
461 return (Engine_Image_Entry *)deie;
462}
463
464static void
465evas_cache_image_dfb_delete(Engine_Image_Entry *eie)
466{
467 free(eie);
468}
469
470static int
471evas_cache_image_dfb_constructor(Engine_Image_Entry *eie, void *data)
472{
473 DirectFB_Engine_Image_Entry *deie = (DirectFB_Engine_Image_Entry *)eie;
474 Render_Engine *re = data;
475 IDirectFBSurface *s;
476 RGBA_Image *im;
477
478 im = (RGBA_Image *)eie->src;
479 if (!im)
480 return EVAS_LOAD_ERROR_NONE; // XXX TODO: confirm?
481
482 evas_cache_image_load_data(&im->cache_entry);
483 if (!im->image.data)
484 return EVAS_LOAD_ERROR_NONE; // XXX TODO: confirm?
485
486 s = _dfb_surface_from_data(re->spec->dfb, eie->w, eie->h, im->image.data);
487 if (!s)
488 return EVAS_LOAD_ERROR_GENERIC;
489
490 deie->surface = s;
491 deie->flags.engine_surface = 0;
492
493 return EVAS_LOAD_ERROR_NONE;
494}
495
496static void
497evas_cache_image_dfb_destructor(Engine_Image_Entry *eie)
498{
499 DirectFB_Engine_Image_Entry *deie = (DirectFB_Engine_Image_Entry *)eie;
500
501 if (!deie->flags.engine_surface)
502 _dfb_surface_free(deie->surface);
503 deie->surface = NULL;
504}
505
506/* note: dst have some properties set, like desired size (w, h) */
507static int
508_cache_image_copy(Engine_Image_Entry *dst, const Engine_Image_Entry *src)
509{
510 DirectFB_Engine_Image_Entry *dst_deie;
511 const DirectFB_Engine_Image_Entry *src_deie;
512 IDirectFBSurface *s;
513 RGBA_Image *im;
514
515 dst_deie = (DirectFB_Engine_Image_Entry *)dst;
516 src_deie = (const DirectFB_Engine_Image_Entry *)src;
517 im = (RGBA_Image *)dst->src;
518 s = _dfb_surface_from_data(dfb, dst->w, dst->h, im->image.data);
519 if (!s)
520 return -1;
521
522 dst_deie->surface = s;
523 dst_deie->flags.engine_surface = 0;
524
525 return 0;
526}
527
528static int
529evas_cache_image_dfb_dirty(Engine_Image_Entry *dst, const Engine_Image_Entry *src)
530{
531 return _cache_image_copy(dst, src);
532}
533
534static void
535evas_cache_image_dfb_dirty_region(Engine_Image_Entry *eim, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
536{
537 RGBA_Image *im;
538
539 im = (RGBA_Image *)eim->src;
540 im->flags |= RGBA_IMAGE_IS_DIRTY;
541}
542
543static int
544evas_cache_image_dfb_update_data(Engine_Image_Entry *dst, void *engine_data)
545{
546 DirectFB_Engine_Image_Entry *deie = (DirectFB_Engine_Image_Entry *)dst;
547 IDirectFBSurface *s = engine_data;
548 Image_Entry *ie;
549 RGBA_Image *im;
550
551 ie = dst->src;
552 im = (RGBA_Image *)ie;
553
554 if (s)
555 {
556 deie->surface = s;
557
558 /* XXX why size is required here? */
559 s->GetSize(s, &dst->w, &dst->h);
560
561 if (im)
562 {
563 im->image.data = NULL; /* IDirectFBSurface requires lock */
564 im->image.no_free = 1;
565 ie->w = dst->w;
566 ie->h = dst->h;
567 _image_autoset_alpha(deie);
568 }
569 }
570 else
571 {
572 _dfb_surface_free(deie->surface);
573 s = _dfb_surface_from_data(dfb, dst->w, dst->h, im->image.data);
574 deie->surface = s;
575 }
576
577 return 0;
578}
579
580static int
581evas_cache_image_dfb_size_set(Engine_Image_Entry *dst, const Engine_Image_Entry *src)
582{
583 return _cache_image_copy(dst, src);
584}
585
586static void
587evas_cache_image_dfb_load(Engine_Image_Entry *eim, const Image_Entry *ie)
588{
589 DirectFB_Engine_Image_Entry *deie = (DirectFB_Engine_Image_Entry *)eim;
590 IDirectFBSurface *s;
591 const RGBA_Image *im;
592
593 if (deie->surface)
594 return;
595
596 im = (const RGBA_Image *)ie;
597 s = _dfb_surface_from_data(dfb, eim->w, eim->h, im->image.data);
598 deie->surface = s;
599}
600
601static int
602evas_cache_image_dfb_mem_size_get(Engine_Image_Entry *eie)
603{
604 DirectFB_Engine_Image_Entry *deie = (DirectFB_Engine_Image_Entry *)eie;
605 DFBResult r;
606 int size, w, h;
607
608 if (!deie->surface)
609 return 0;
610
611 size = sizeof(*deie->surface);
612
613 r = deie->surface->GetSize(deie->surface, &w, &h);
614 if (r != DFB_OK)
615 {
616 ERR("Could not get surface size: %s",
617 DirectFBErrorString(r));
618 return size;
619 }
620
621 size += w * h * 4; // XXX get correct surface size using pixelformat
622
623 return size;
624}
625
626#ifdef DFB_DEBUG_IMAGE
627static void
628evas_cache_image_dfb_debug(const char *context, Engine_Image_Entry* eie)
629{
630 DirectFB_Engine_Image_Entry *eim = (DirectFB_Engine_Image_Entry *)eie;
631
632 DBG("*** %s image (%p) ***", context, eim);
633 if (eim)
634 {
635 DBG("W: %d, H: %d, R: %d, Key: %s, DFB Surface: %p",
636 eie->w, eie->h, eie->references, eie->cache_key, eim->surface);
637
638 if (eie->src)
639 DBG("Pixels: %p", ((RGBA_Image*) eie->src)->image.data);
640 }
641 DBG("*** ***");
642}
643#endif
644
645static const Evas_Cache_Engine_Image_Func _dfb_cache_engine_image_cb = {
646 NULL /* key */,
647 evas_cache_image_dfb_alloc /* alloc */,
648 evas_cache_image_dfb_delete /* dealloc */,
649 evas_cache_image_dfb_constructor /* constructor */,
650 evas_cache_image_dfb_destructor /* destructor */,
651 evas_cache_image_dfb_dirty_region /* dirty_region */,
652 evas_cache_image_dfb_dirty /* dirty */,
653 evas_cache_image_dfb_size_set /* size_set */,
654 evas_cache_image_dfb_update_data /* update_data */,
655 evas_cache_image_dfb_load /* load */,
656 evas_cache_image_dfb_mem_size_get /* mem_size_get */,
657#ifdef DFB_DEBUG_IMAGE /* debug */
658 evas_cache_image_dfb_debug
659#else
660 NULL
661#endif
662};
663
664
665/***********************************************************************
666 * Evas Engine
667 **********************************************************************/
668static void *
669evas_engine_dfb_info(Evas* e __UNUSED__)
670{
671 Evas_Engine_Info_DirectFB *info;
672 info = calloc(1, sizeof(Evas_Engine_Info_DirectFB));
673 if (!info)
674 return NULL;
675 info->magic.magic = rand();
676 return info;
677}
678
679static void
680evas_engine_dfb_info_free(Evas *e __UNUSED__, void *in)
681{
682 Evas_Engine_Info_DirectFB *info = in;
683 free(info);
684}
685
686static Eina_Bool
687_is_dfb_data_ok(IDirectFB *idfb, IDirectFBSurface *surface, int w, int h)
688{
689 DFBResult r;
690 int sw, sh;
691
692 if (!idfb)
693 {
694 ERR("missing IDirectFB");
695 return EINA_FALSE;
696 }
697 dfb = idfb;
698
699 if (!surface)
700 {
701 ERR("missing IDirectFBSurface");
702 return EINA_FALSE;
703 }
704
705 r = surface->GetSize(surface, &sw, &sh);
706 if (r != DFB_OK)
707 {
708 ERR("Could not get surface %p size: %s",
709 surface, DirectFBErrorString(r));
710 return EINA_FALSE;
711 }
712
713 if ((w > sw) || (h > sh))
714 {
715 ERR("Requested size is larger than surface: %dx%d > %dx%d",
716 w, h, sw, sh);
717 return EINA_FALSE;
718 }
719 else if ((w <= 0) || (h <= 0))
720 {
721 w = sw;
722 h = sh;
723 }
724
725 return EINA_TRUE;
726}
727
728static void
729_evas_common_init(void)
730{
731 evas_common_cpu_init();
732 evas_common_blend_init();
733 evas_common_image_init();
734 evas_common_convert_init();
735 evas_common_scale_init();
736 evas_common_rectangle_init();
737 evas_common_polygon_init();
738 evas_common_line_init();
739 evas_common_font_init();
740 evas_common_draw_init();
741 evas_common_tilebuf_init();
742}
743
744static int
745evas_engine_dfb_output_reconfigure(Render_Engine *re, int w, int h)
746{
747 if (re->screen_image)
748 evas_cache_engine_image_drop(&re->screen_image->cache_entry);
749
750 if (re->tb)
751 evas_common_tilebuf_free(re->tb);
752
753 re->tb = evas_common_tilebuf_new(w, h);
754 if (!re->tb)
755 {
756 ERR("Could not allocate tile buffer.");
757 goto failed_tilebuf;
758 }
759 evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE);
760
761 /* We create a "fake" RGBA_Image which points to the IDirectFB surface.
762 * Each access to that surface is wrapped in Lock / Unlock calls whenever
763 * the data is manipulated directly.
764 */
765 re->screen_image = (DirectFB_Engine_Image_Entry *)
766 evas_cache_engine_image_engine(re->cache, re->spec->surface);
767 if (!re->screen_image)
768 {
769 ERR("RGBA_Image allocation from DFB failed");
770 goto failed_image;
771 }
772 re->screen_image->flags.engine_surface = 1;
773
774 _image_autoset_alpha(re->screen_image);
775 _image_clear(re->screen_image, 0, 0, w, h);
776
777 return 1;
778
779 failed_image:
780 evas_common_tilebuf_free(re->tb);
781 re->tb = NULL;
782 failed_tilebuf:
783 re->screen_image = NULL;
784 ERR("Evas DirectFB reconfigure failed");
785 return 0;
786}
787
788static void *
789_dfb_output_setup(int w, int h, const struct Evas_Engine_DirectFB_Spec *spec)
790{
791 Render_Engine *re;
792
793 if (!_is_dfb_data_ok(spec->dfb, spec->surface, w, h))
794 goto fatal;
795
796 _evas_common_init();
797
798 re = calloc(1, sizeof(Render_Engine));
799 if (!re)
800 {
801 perror("calloc");
802 goto fatal;
803 }
804 re->dfb = spec->dfb;
805 re->spec = spec;
806 re->cache = evas_cache_engine_image_init(&_dfb_cache_engine_image_cb,
807 evas_common_image_cache_get());
808 if (!re->cache)
809 {
810 ERR("Evas_Cache_Engine_Image allocation failed!");
811 goto fatal_after_engine;
812 }
813
814 if (!evas_engine_dfb_output_reconfigure(re, w, h))
815 {
816 ERR("Could not reconfigure evas engine.");
817 goto fatal_after_reconfigure;
818 }
819
820 _dfb_blit_accel_caps_print(spec->surface, NULL);
821
822 return re;
823
824
825 fatal_after_reconfigure:
826 evas_cache_engine_image_shutdown(re->cache);
827 fatal_after_engine:
828 free(re);
829 fatal:
830 CRIT("DirectFB: unable to continue, abort()!");
831 abort();
832 return NULL;
833}
834
835static int
836evas_engine_dfb_setup(Evas *e, void *in)
837{
838 Evas_Engine_Info_DirectFB *info = in;
839
840 if (!e->engine.data.output)
841 e->engine.data.output = _dfb_output_setup(e->output.w, e->output.h,
842 &info->info);
843 // XXX TODO: else reconfigure existing...
844
845 if (!e->engine.data.output)
846 return 0;
847
848 if (!e->engine.data.context)
849 e->engine.data.context =
850 e->engine.func->context_new(e->engine.data.output);
851
852 return 1;
853}
854
855static void
856evas_engine_dfb_output_free(void *data)
857{
858 Render_Engine *re = data;
859
860 if (!re)
861 return;
862
863 if (re->cache)
864 evas_cache_engine_image_shutdown(re->cache);
865
866 evas_common_tilebuf_free(re->tb);
867 if (re->rects) evas_common_tilebuf_free_render_rects(re->rects);
868 free(re);
869
870 evas_common_font_shutdown();
871 evas_common_image_shutdown();
872}
873
874static void
875evas_engine_dfb_output_resize(void *data, int w, int h)
876{
877 if (!evas_engine_dfb_output_reconfigure(data, w, h))
878 ERR("Failed to resize DirectFB evas");
879}
880
881static void
882evas_engine_dfb_output_tile_size_set(void *data, int w, int h)
883{
884 Render_Engine *re = data;
885
886 evas_common_tilebuf_set_tile_size(re->tb, w, h);
887}
888
889static void
890evas_engine_dfb_output_redraws_rect_add(void *data, int x, int y, int w, int h)
891{
892 Render_Engine *re = data;
893
894 evas_common_tilebuf_add_redraw(re->tb, x, y, w, h);
895}
896
897static void
898evas_engine_dfb_output_redraws_rect_del(void *data, int x, int y, int w, int h)
899{
900 Render_Engine *re = data;
901
902 evas_common_tilebuf_del_redraw(re->tb, x, y, w, h);
903}
904
905static void
906evas_engine_dfb_output_redraws_clear(void *data)
907{
908 Render_Engine *re = data;
909
910 evas_common_tilebuf_clear(re->tb);
911}
912
913static void *
914evas_engine_dfb_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, int *cx, int *cy, int *cw, int *ch)
915{
916 Render_Engine *re = data;
917 Tilebuf_Rect *tb_rect;
918
919 if (re->end)
920 {
921 re->end = 0;
922 return NULL;
923 }
924 if (!re->rects)
925 {
926 re->rects = evas_common_tilebuf_get_render_rects(re->tb);
927 re->cur_rect = EINA_INLIST_GET(re->rects);
928 }
929 if (!re->cur_rect)
930 return NULL;
931
932 tb_rect = (Tilebuf_Rect*) re->cur_rect;
933 *cx = *x = tb_rect->x;
934 *cy = *y = tb_rect->y;
935 *cw = *w = tb_rect->w;
936 *ch = *h = tb_rect->h;
937 re->cur_rect = re->cur_rect->next;
938 if (!re->cur_rect)
939 {
940 evas_common_tilebuf_free_render_rects(re->rects);
941 re->rects = NULL;
942 re->end = 1;
943 }
944
945 return re->screen_image;
946}
947
948static void
949evas_engine_dfb_output_redraws_next_update_push(void *data, void *surface __UNUSED__, int x, int y, int w, int h)
950{
951 Render_Engine *re = data;
952 DFBRegion *r;
953
954 if (re->update_regions_count >= re->update_regions_limit)
955 {
956 void *tmp;
957
958 re->update_regions_limit += 16;
959
960 tmp = realloc(re->update_regions,
961 sizeof(DFBRegion) * re->update_regions_limit);
962 if (!tmp)
963 {
964 perror("realloc");
965 return;
966 }
967 re->update_regions = tmp;
968 }
969
970 r = re->update_regions + re->update_regions_count;
971 re->update_regions_count++;
972
973 r->x1 = x;
974 r->y1 = y;
975 r->x2 = x + w - 1;
976 r->y2 = y + h - 1;
977}
978
979static void
980evas_engine_dfb_output_flush(void *data)
981{
982 Render_Engine *re = data;
983 IDirectFBSurface *s = re->screen_image->surface;
984 DFBRegion *r, *r_end;
985
986 r = re->update_regions;
987 r_end = re->update_regions + re->update_regions_count;
988
989#ifdef DFB_UPDATE_INDIVIDUAL_RECTS
990 for (; r < r_end; r++)
991 s->Flip(s, r, DFB_FLIP_FLAGS);
992#else
993 DFBRegion bb;
994
995 bb.x1 = bb.y1 = 10000;
996 bb.x2 = bb.y2 = 0;
997 for (; r < r_end; r++)
998 {
999 if (bb.x1 > r->x1)
1000 bb.x1 = r->x1;
1001 if (bb.y1 > r->y1)
1002 bb.y1 = r->y1;
1003
1004 if (bb.x2 < r->x2)
1005 bb.x2 = r->x2;
1006 if (bb.y2 < r->y2)
1007 bb.y2 = r->y2;
1008 }
1009
1010 s->Flip(s, &bb, DFB_FLIP_FLAGS);
1011#endif
1012
1013 re->update_regions_count = 0;
1014}
1015
1016static void
1017evas_engine_dfb_output_idle_flush(void *data)
1018{
1019 Render_Engine *re = data;
1020
1021 if (re->update_regions_count != 0)
1022 ERR("update_regions_count not 0 as it should be!");
1023
1024 free(re->update_regions);
1025 re->update_regions_count = 0;
1026 re->update_regions_limit = 0;
1027 re->update_regions = NULL;
1028}
1029
1030/* HACK!!! -- KLUDGE!!!
1031 *
1032 * This should really use IDirectFBFont and IDirectFBSurface::DrawString(),
1033 * but to be edje-compatible IDirectFBFont::CreateFont() should be able to
1034 * load fonts from non-files, which it does not.
1035 *
1036 * Try to find a way to create own IDirectFBFont in future and load from
1037 * memory.
1038 */
1039static void
1040evas_engine_dfb_font_draw(void *data, 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)
1041{
1042 DirectFB_Engine_Image_Entry *eim = surface;
1043 IDirectFBSurface *screen;
1044 Render_Engine *re = data;
1045 RGBA_Image *im;
1046
1047 im = (RGBA_Image *)eim->cache_entry.src;
1048 screen = eim->surface;
1049 if (!_dfb_lock_and_sync_image(screen, im, DSLF_READ | DSLF_WRITE))
1050 return;
1051
1052 evas_common_font_draw(im, context, font, x, y, intl_props);
1053 evas_common_cpu_end_opt();
1054
1055 im->image.data = NULL;
1056
1057 screen->Unlock(screen);
1058}
1059
1060
1061static void
1062_cb_draw_line(IDirectFBSurface *surface, RGBA_Draw_Context *dc __UNUSED__, const DFBRegion *region __UNUSED__, void *data)
1063{
1064 const Eina_Rectangle *r = data;
1065
1066 surface->DrawLine(surface, r->x, r->y, r->w, r->h); /* x2, y2 really */
1067}
1068
1069static void
1070evas_engine_dfb_line_draw(void *data __UNUSED__, void *context, void *surface, int x1, int y1, int x2, int y2)
1071{
1072 DirectFB_Engine_Image_Entry *eim = surface;
1073 Eina_Rectangle r;
1074
1075 if (!_dfb_surface_set_color_from_context(eim->surface, context))
1076 return;
1077
1078 EINA_RECTANGLE_SET(&r, x1, y1, x2, y2); /* x2, y2 (ab)used as w, h */
1079 _dfb_surface_for_each_cutout(eim->surface, context, _cb_draw_line, &r);
1080}
1081
1082#ifndef DFB_USE_EVAS_RECT_DRAW
1083static void
1084_cb_draw_rectangle(IDirectFBSurface *surface, RGBA_Draw_Context *dc __UNUSED__, const DFBRegion *region __UNUSED__, void *data)
1085{
1086 const Eina_Rectangle *r = data;
1087
1088 surface->FillRectangle(surface, r->x, r->y, r->w, r->h);
1089}
1090
1091static void
1092evas_engine_dfb_rectangle_draw(void *data, void *context, void *surface, int x, int y, int w, int h)
1093{
1094 DirectFB_Engine_Image_Entry *eim = surface;
1095 IDirectFBSurface *screen;
1096 Render_Engine *re = data;
1097 RGBA_Draw_Context *dc = context;
1098 Eina_Rectangle r;
1099
1100 screen = eim->surface;
1101 if (!_dfb_surface_set_color_from_context(screen, context))
1102 {
1103 if (dc->render_op != EVAS_RENDER_COPY)
1104 return;
1105 if (!eim->cache_entry.src->flags.alpha)
1106 return;
1107 screen->SetColor(screen, 0, 0, 0, 0);
1108 screen->SetDrawingFlags(screen, DSDRAW_NOFX);
1109 }
1110
1111 EINA_RECTANGLE_SET(&r, x, y, w, h);
1112 _dfb_surface_for_each_cutout(screen, context, _cb_draw_rectangle, &r);
1113}
1114#else
1115static void
1116evas_engine_dfb_rectangle_draw(void *data, void *context, void *surface, int x, int y, int w, int h)
1117{
1118 DirectFB_Engine_Image_Entry *eim = surface;
1119 IDirectFBSurface *screen;
1120 Render_Engine *re = data;
1121 RGBA_Image *dst;
1122
1123 dst = (RGBA_Image *)eim->cache_entry.src;
1124 screen = eim->surface;
1125 if (!_dfb_lock_and_sync_image(screen, dst, DSLF_READ | DSLF_WRITE))
1126 return;
1127
1128 evas_common_rectangle_draw(dst, context, x, y, w, h);
1129 evas_common_cpu_end_opt();
1130
1131 dst->image.data = NULL;
1132
1133 screen->Unlock(screen);
1134}
1135#endif
1136
1137#ifndef DFB_USE_EVAS_POLYGON_DRAW
1138static void
1139evas_engine_dfb_polygon_draw(void *data __UNUSED__, void *context, void *surface, void *polygon, int x, int y)
1140{
1141 _dfb_polygon_draw(surface, context, polygon, x, y);
1142}
1143#else
1144static void
1145evas_engine_dfb_polygon_draw(void *data, void *context, void *surface, void *polygon, int x, int y)
1146{
1147 DirectFB_Engine_Image_Entry *eim = surface;
1148 IDirectFBSurface *screen;
1149 Render_Engine *re = data;
1150 RGBA_Image *dst;
1151
1152 dst = (RGBA_Image *)eim->cache_entry.src;
1153 screen = eim->surface;
1154 if (!_dfb_lock_and_sync_image(screen, dst, DSLF_READ | DSLF_WRITE))
1155 return;
1156
1157 evas_common_polygon_draw(dst, context, polygon, x, y);
1158 evas_common_cpu_end_opt();
1159
1160 dst->image.data = NULL;
1161
1162 screen->Unlock(screen);
1163}
1164#endif
1165
1166/** Image Object *******************************************************/
1167static void *
1168evas_engine_dfb_image_load(void *data, const char *file, const char *key, int *error, Evas_Image_Load_Opts *lo)
1169{
1170 Render_Engine *re = data;
1171
1172 *error = 0;
1173 return evas_cache_engine_image_request(re->cache, file, key, lo,
1174 data, error);
1175}
1176
1177static int
1178evas_engine_dfb_image_alpha_get(void *data __UNUSED__, void *image)
1179{
1180 DirectFB_Engine_Image_Entry *eim = image;
1181 Image_Entry *ie;
1182 RGBA_Image *im;
1183
1184 if (!eim) return 1;
1185 ie = eim->cache_entry.src;
1186 im = (RGBA_Image *)ie;
1187 switch (ie->space)
1188 {
1189 case EVAS_COLORSPACE_ARGB8888:
1190 if (ie->flags.alpha) return 1;
1191 default:
1192 break;
1193 }
1194 return 0;
1195}
1196
1197static void
1198evas_engine_dfb_image_size_get(void *data __UNUSED__, void *image, int *w, int *h)
1199{
1200 DirectFB_Engine_Image_Entry *eim = image;
1201 Image_Entry *ie;
1202
1203 ie = eim->cache_entry.src;
1204 if (w) *w = ie->w;
1205 if (h) *h = ie->h;
1206}
1207
1208static int
1209evas_engine_dfb_image_colorspace_get(void *data __UNUSED__, void *image)
1210{
1211 DirectFB_Engine_Image_Entry *eim = image;
1212
1213 if (!eim) return EVAS_COLORSPACE_ARGB8888;
1214 return eim->cache_entry.src->space;
1215}
1216
1217static void
1218evas_engine_dfb_image_colorspace_set(void *data, void *image, int cspace)
1219{
1220 DirectFB_Engine_Image_Entry *eim = image;
1221
1222 if (!eim) return;
1223 if (eim->cache_entry.src->space == cspace) return;
1224
1225 evas_cache_engine_image_colorspace(&eim->cache_entry, cspace, data);
1226}
1227
1228static void *
1229evas_engine_dfb_image_new_from_copied_data(void *data, int w, int h, DATA32* image_data, int alpha, int cspace)
1230{
1231 Render_Engine *re = data;
1232
1233 return evas_cache_engine_image_copied_data(re->cache, w, h, image_data,
1234 alpha, cspace, NULL);
1235}
1236
1237static void *
1238evas_engine_dfb_image_new_from_data(void *data, int w, int h, DATA32* image_data, int alpha, int cspace)
1239{
1240 Render_Engine *re = data;
1241
1242 return evas_cache_engine_image_data(re->cache, w, h, image_data,
1243 alpha, cspace, NULL);
1244}
1245
1246static void
1247evas_engine_dfb_image_free(void *data __UNUSED__, void *image)
1248{
1249 DirectFB_Engine_Image_Entry *eim = image;
1250
1251 evas_cache_engine_image_drop(&eim->cache_entry);
1252}
1253
1254static void *
1255evas_engine_dfb_image_size_set(void *data __UNUSED__, void *image, int w, int h)
1256{
1257 DirectFB_Engine_Image_Entry *eim = image;
1258
1259 return evas_cache_engine_image_size_set(&eim->cache_entry, w, h);
1260}
1261
1262static void *
1263evas_engine_dfb_image_dirty_region(void *data __UNUSED__, void *image, int x, int y, int w, int h)
1264{
1265 DirectFB_Engine_Image_Entry *eim = image;
1266
1267 return evas_cache_engine_image_dirty(&eim->cache_entry, x, y, w, h);
1268}
1269
1270static void *
1271evas_engine_dfb_image_data_get(void *data __UNUSED__, void *image, int to_write, DATA32** image_data)
1272{
1273 DirectFB_Engine_Image_Entry *deie = image;
1274 Engine_Image_Entry *ce;
1275 Image_Entry *ie;
1276 RGBA_Image *im;
1277
1278 if (!deie)
1279 {
1280 *image_data = NULL;
1281 return NULL;
1282 }
1283
1284 ce = (Engine_Image_Entry *)deie;
1285 ie = ce->src;
1286 im = (RGBA_Image *)ie;
1287
1288 switch (ie->space)
1289 {
1290 case EVAS_COLORSPACE_ARGB8888:
1291 {
1292 DFBResult r;
1293 IDirectFBSurface *s;
1294 void *pixels;
1295 int pitch;
1296
1297 if (to_write)
1298 deie = (DirectFB_Engine_Image_Entry *)
1299 evas_cache_engine_image_dirty(ce, 0, 0, ie->w, ie->h);
1300
1301 evas_cache_engine_image_load_data(ce);
1302
1303 ce = (Engine_Image_Entry *)deie;
1304 ie = ce->src;
1305 im = (RGBA_Image *)ie;
1306 s = deie->surface;
1307
1308 if (to_write)
1309 {
1310 r = s->Lock(s, DSLF_WRITE, &pixels, &pitch);
1311 if (r != DFB_OK)
1312 goto error;
1313 deie->flags.is_locked = 1;
1314 }
1315 else
1316 {
1317 r = s->Lock(s, DSLF_READ, &pixels, &pitch);
1318 if (r != DFB_OK)
1319 goto error;
1320 s->Unlock(s);
1321 }
1322
1323 *image_data = pixels;
1324 im->image.data = pixels; /* remember for _put() */
1325 break;
1326
1327 error:
1328 ERR("Could not lock surface %p: %s",
1329 s, DirectFBErrorString(r));
1330 *image_data = NULL;
1331 break;
1332 }
1333 case EVAS_COLORSPACE_YCBCR422P709_PL:
1334 case EVAS_COLORSPACE_YCBCR422P601_PL:
1335 case EVAS_COLORSPACE_YCBCR422601_PL:
1336 /* XXX untested */
1337 *image_data = im->cs.data;
1338 break;
1339 default:
1340 abort();
1341 break;
1342 }
1343 return deie;
1344}
1345
1346static void *
1347evas_engine_dfb_image_data_put(void *data, void *image, DATA32* image_data)
1348{
1349 DirectFB_Engine_Image_Entry *deie = image;
1350 Render_Engine *re = data;
1351 Engine_Image_Entry *ce;
1352 Image_Entry *ie;
1353 RGBA_Image *im;
1354
1355 if (!deie) return NULL;
1356
1357 ce = (Engine_Image_Entry *)deie;
1358 ie = ce->src;
1359 im = (RGBA_Image*)ie;
1360
1361 switch (ie->space)
1362 {
1363 case EVAS_COLORSPACE_ARGB8888:
1364 if (image_data == im->image.data)
1365 {
1366 if (deie->flags.is_locked)
1367 {
1368 deie->surface->Unlock(deie->surface);
1369 deie->flags.is_locked = 0;
1370 }
1371 }
1372 else
1373 {
1374 int alpha, cspace;
1375
1376 alpha = func.image_alpha_get(re, deie);
1377 cspace = func.image_colorspace_get(re, deie);
1378
1379 evas_cache_engine_image_drop(ce);
1380 deie = (DirectFB_Engine_Image_Entry *)
1381 evas_cache_engine_image_data(re->cache, ce->w, ce->h,
1382 image_data, alpha, cspace, NULL);
1383 }
1384 break;
1385 case EVAS_COLORSPACE_YCBCR422P601_PL:
1386 case EVAS_COLORSPACE_YCBCR422P709_PL:
1387 case EVAS_COLORSPACE_YCBCR422601_PL:
1388 /* XXX untested */
1389 if (image_data != im->cs.data)
1390 {
1391 if (im->cs.data)
1392 if (!im->cs.no_free)
1393 free(im->cs.data);
1394 im->cs.data = image_data;
1395 evas_common_image_colorspace_dirty(im);
1396 }
1397 break;
1398 default:
1399 abort();
1400 break;
1401 }
1402 return deie;
1403}
1404
1405static void
1406evas_engine_dfb_image_data_preload_request(void *data __UNUSED__, void *image, const void *target)
1407{
1408 DirectFB_Engine_Image_Entry *deie = image;
1409 RGBA_Image *im;
1410
1411 if (!deie) return ;
1412 im = (RGBA_Image*) deie->cache_entry.src;
1413 if (!im) return ;
1414 evas_cache_image_preload_data(&im->cache_entry, target);
1415}
1416
1417static void
1418evas_engine_dfb_image_data_preload_cancel(void *data __UNUSED__, void *image, const void *target)
1419{
1420 DirectFB_Engine_Image_Entry *deie = image;
1421 RGBA_Image *im;
1422
1423 if (!deie) return ;
1424 im = (RGBA_Image*) deie->cache_entry.src;
1425 if (!im) return ;
1426 evas_cache_image_preload_cancel(&im->cache_entry, target);
1427}
1428
1429static void *
1430evas_engine_dfb_image_alpha_set(void *data __UNUSED__, void *image, int has_alpha)
1431{
1432 DirectFB_Engine_Image_Entry *eim = image;
1433 Engine_Image_Entry *ce;
1434 Image_Entry *ie;
1435 RGBA_Image *im;
1436
1437 if (!eim) return NULL;
1438
1439 ce = &eim->cache_entry;
1440 ie = ce->src;
1441 im = (RGBA_Image*)ie;
1442
1443 if (ie->space != EVAS_COLORSPACE_ARGB8888)
1444 {
1445 ie->flags.alpha = 0;
1446 return eim;
1447 }
1448
1449 eim = (DirectFB_Engine_Image_Entry *)
1450 evas_cache_engine_image_dirty(ce, 0, 0, ce->w, ce->h);
1451
1452 ie->flags.alpha = !!has_alpha;
1453 return eim;
1454}
1455
1456struct _for_each_cutout_image
1457{
1458 IDirectFBSurface *image;
1459 DFBRectangle src, dst;
1460};
1461
1462static void
1463_cb_draw_image_unscaled(IDirectFBSurface *surface, RGBA_Draw_Context *dc __UNUSED__, const DFBRegion *region __UNUSED__, void *data)
1464{
1465 const struct _for_each_cutout_image *p = data;
1466
1467 surface->Blit(surface, p->image, &p->src, p->dst.x, p->dst.y);
1468}
1469
1470static void
1471_cb_draw_image_scaled(IDirectFBSurface *surface, RGBA_Draw_Context *dc __UNUSED__, const DFBRegion *region __UNUSED__, void *data)
1472{
1473 const struct _for_each_cutout_image *p = data;
1474
1475 surface->StretchBlit(surface, p->image, &p->src, &p->dst);
1476}
1477
1478#ifndef DFB_USE_EVAS_IMAGE_DRAW
1479static void
1480evas_engine_dfb_image_draw(void *data, void *context, void *surface, void *image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int dst_w, int dst_h, int smooth __UNUSED__)
1481{
1482 DirectFB_Engine_Image_Entry *eim = surface;
1483 Render_Engine *re = data;
1484 IDirectFBSurface *screen;
1485 DirectFB_Engine_Image_Entry *deie = image;
1486 struct _for_each_cutout_image p;
1487 _cb_for_each_cutout_t cb;
1488
1489 screen = eim->surface;
1490 if (deie->cache_entry.src->space == EVAS_COLORSPACE_ARGB8888)
1491 evas_cache_engine_image_load_data(&deie->cache_entry);
1492
1493 evas_common_image_colorspace_normalize((RGBA_Image *)deie->cache_entry.src);
1494
1495 _dfb_surface_set_blit_params(eim, deie, context);
1496
1497 _dfb_rect_set(&p.src, src_x, src_y, src_w, src_h);
1498 _dfb_rect_set(&p.dst, dst_x, dst_y, dst_w, dst_h);
1499 p.image = deie->surface;
1500
1501 if ((src_w == dst_w) && (src_h == dst_h))
1502 cb = _cb_draw_image_unscaled;
1503 else
1504 cb = _cb_draw_image_scaled;
1505
1506 _dfb_blit_accel_caps_print(screen, deie->surface);
1507 _dfb_surface_for_each_cutout(screen, context, cb, &p);
1508}
1509#else /* DFB_USE_EVAS_IMAGE_DRAW */
1510static void
1511evas_engine_dfb_image_draw(void *data, void *context, void *surface, void *image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int dst_w, int dst_h, int smooth)
1512{
1513 DirectFB_Engine_Image_Entry *deie = image;
1514 DirectFB_Engine_Image_Entry *eim = surface;
1515 Render_Engine *re = data;
1516 RGBA_Image *dst, *src;
1517 IDirectFBSurface *screen;
1518
1519 screen = eim->surface;
1520 if (deie->cache_entry.src->space == EVAS_COLORSPACE_ARGB8888)
1521 evas_cache_engine_image_load_data(&deie->cache_entry);
1522
1523 evas_common_image_colorspace_normalize((RGBA_Image *)deie->cache_entry.src);
1524
1525 dst = (RGBA_Image *)eim->cache_entry.src;
1526 if (!_dfb_lock_and_sync_image(screen, dst, DSLF_READ | DSLF_WRITE))
1527 return;
1528
1529 src = (RGBA_Image *)deie->cache_entry.src;
1530 if (!_dfb_lock_and_sync_image(deie->surface, src, DSLF_READ))
1531 goto error_src;
1532
1533 if (smooth)
1534 evas_common_scale_rgba_in_to_out_clip_smooth(src, dst, context,
1535 src_x, src_y, src_w, src_h,
1536 dst_x, dst_y, dst_w, dst_h);
1537 else
1538 evas_common_scale_rgba_in_to_out_clip_sample(src, dst, context,
1539 src_x, src_y, src_w, src_h,
1540 dst_x, dst_y, dst_w, dst_h);
1541 evas_common_cpu_end_opt();
1542
1543 dst->image.data = NULL;
1544
1545 screen->Unlock(screen);
1546 deie->surface->Unlock(deie->surface);
1547
1548 return;
1549
1550 error_src:
1551 screen->Unlock(screen);
1552}
1553#endif
1554
1555static void
1556evas_engine_dfb_image_map_draw(void *data __UNUSED__, void *context, void *surface, void *image, int npoints, RGBA_Map_Point *p, int smooth, int level)
1557{
1558 Render_Engine *re = (Render_Engine*) data;
1559 DirectFB_Engine_Image_Entry *deie = image;
1560 DirectFB_Engine_Image_Entry *eim = surface;
1561 IDirectFBSurface *screen;
1562 RGBA_Image *dst, *src;
1563
1564 if (!deie || !eim) return ;
1565
1566 screen = eim->surface;
1567 dst = (RGBA_Image *) eim->cache_entry.src;
1568 if (!_dfb_lock_and_sync_image(screen, dst, DSLF_READ | DSLF_WRITE))
1569 return;
1570
1571 src = (RGBA_Image *)deie->cache_entry.src;
1572 if (!_dfb_lock_and_sync_image(deie->surface, src, DSLF_READ))
1573 goto error_src;
1574
1575 evas_common_map_rgba(src, dst, context, 4, p, smooth, level);
1576 evas_common_cpu_end_opt();
1577
1578 screen->Unlock(screen);
1579 deie->surface->Unlock(deie->surface);
1580
1581 return ;
1582
1583 error_src:
1584 screen->Unlock(screen);
1585}
1586
1587static void *
1588evas_engine_dfb_image_map_surface_new(void *data, int w, int h, int alpha)
1589{
1590 Render_Engine *re = (Render_Engine*) data;
1591 void *surface;
1592
1593 surface = evas_cache_engine_image_copied_data(re->cache,
1594 w, h, NULL, alpha,
1595 EVAS_COLORSPACE_ARGB8888,
1596 NULL);
1597 return surface;
1598}
1599
1600static void
1601evas_engine_dfb_image_map_surface_free(void *data __UNUSED__, void *surface)
1602{
1603 evas_cache_engine_image_drop(surface);
1604}
1605
1606
1607static void
1608evas_engine_dfb_image_cache_flush(void *data)
1609{
1610 Render_Engine *re = data;
1611 int size;
1612
1613 size = evas_cache_engine_image_get(re->cache);
1614 evas_cache_engine_image_set(re->cache, 0);
1615 evas_cache_engine_image_set(re->cache, size);
1616}
1617
1618static void
1619evas_engine_dfb_image_cache_set(void *data, int bytes)
1620{
1621 Render_Engine *re = data;
1622
1623 evas_cache_engine_image_set(re->cache, bytes);
1624}
1625
1626static int
1627evas_engine_dfb_image_cache_get(void *data)
1628{
1629 Render_Engine *re = data;
1630
1631 return evas_cache_engine_image_get(re->cache);
1632}
1633
1634static char *
1635evas_engine_dfb_image_comment_get(void *data __UNUSED__, void *image, char *key __UNUSED__)
1636{
1637 DirectFB_Engine_Image_Entry *eim = image;
1638 RGBA_Image *im;
1639
1640 if (!eim) return NULL;
1641 im = (RGBA_Image *)eim->cache_entry.src;
1642
1643 return im->info.comment;
1644}
1645
1646static void
1647evas_engine_dfb_image_scale_hint_set(void *data __UNUSED__, void *image, int hint)
1648{
1649}
1650
1651static int
1652evas_engine_dfb_image_scale_hint_get(void *data __UNUSED__, void *image)
1653{
1654 return EVAS_IMAGE_SCALE_HINT_NONE;
1655}
1656
1657static Eina_Bool
1658evas_engine_dfb_canvas_alpha_get(void *data, void *context)
1659{
1660 Render_Engine *re = data;
1661
1662 return re->screen_image->cache_entry.src->flags.alpha;
1663}
1664
1665static int
1666module_open(Evas_Module *em)
1667{
1668 if (!em) return 0;
1669 /* get whatever engine module we inherit from */
1670 if (!_evas_module_engine_inherit(&parent_func, "software_generic")) return 0;
1671 _evas_engine_directfb_log_dom = eina_log_domain_register
1672 ("evas-directfb", EVAS_DEFAULT_LOG_COLOR);
1673 if (_evas_engine_directfb_log_dom < 0)
1674 {
1675 EINA_LOG_ERR("Can not create a module log domain.");
1676 return 0;
1677 }
1678 /* store it for later use */
1679 func = parent_func;
1680 /* now to override methods */
1681#define ORD(f) EVAS_API_OVERRIDE(f, &func, evas_engine_dfb_)
1682 ORD(info);
1683 ORD(info_free);
1684 ORD(setup);
1685 ORD(canvas_alpha_get);
1686 ORD(output_free);
1687 ORD(output_resize);
1688 ORD(output_tile_size_set);
1689 ORD(output_redraws_rect_add);
1690 ORD(output_redraws_rect_del);
1691 ORD(output_redraws_clear);
1692 ORD(output_redraws_next_update_get);
1693 ORD(output_redraws_next_update_push);
1694 ORD(output_flush);
1695 ORD(output_idle_flush);
1696 ORD(image_load);
1697 ORD(image_new_from_data);
1698 ORD(image_new_from_copied_data);
1699 ORD(image_colorspace_set);
1700 ORD(image_colorspace_get);
1701 ORD(image_free);
1702 ORD(image_size_set);
1703 ORD(image_size_get);
1704 ORD(image_dirty_region);
1705 ORD(image_data_get);
1706 ORD(image_data_put);
1707 ORD(image_data_preload_request);
1708 ORD(image_data_preload_cancel);
1709 ORD(image_alpha_set);
1710 ORD(image_alpha_get);
1711 ORD(image_draw);
1712 ORD(image_comment_get);
1713 ORD(image_cache_flush);
1714 ORD(image_cache_set);
1715 ORD(image_cache_get);
1716 ORD(font_draw);
1717 ORD(line_draw);
1718 ORD(rectangle_draw);
1719 ORD(polygon_draw);
1720 ORD(image_scale_hint_set);
1721 ORD(image_scale_hint_get);
1722
1723 ORD(image_map_draw);
1724 ORD(image_map_surface_new);
1725 ORD(image_map_surface_free);
1726
1727 /* now advertise out own api */
1728 em->functions = (void *)(&func);
1729 return 1;
1730}
1731
1732static void
1733module_close(Evas_Module *em)
1734{
1735 eina_log_domain_unregister(_evas_engine_directfb_log_dom);
1736}
1737
1738static Evas_Module_Api evas_modapi =
1739{
1740 EVAS_MODULE_API_VERSION,
1741 "directfb",
1742 "ProFUSION embedded systems",
1743 {
1744 module_open,
1745 module_close
1746 }
1747};
1748
1749EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_ENGINE, engine, directfb);
1750
1751#ifndef EVAS_STATIC_BUILD_DIRECTFB
1752EVAS_EINA_MODULE_DEFINE(engine, directfb);
1753#endif