aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/evas/src/modules/engines/software_16_x11/evas_engine.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/evas/src/modules/engines/software_16_x11/evas_engine.c')
-rw-r--r--libraries/evas/src/modules/engines/software_16_x11/evas_engine.c741
1 files changed, 741 insertions, 0 deletions
diff --git a/libraries/evas/src/modules/engines/software_16_x11/evas_engine.c b/libraries/evas/src/modules/engines/software_16_x11/evas_engine.c
new file mode 100644
index 0000000..5378972
--- /dev/null
+++ b/libraries/evas/src/modules/engines/software_16_x11/evas_engine.c
@@ -0,0 +1,741 @@
1#include "evas_common.h"
2#include "evas_private.h"
3#include "evas_engine.h"
4#include "Evas_Engine_Software_16_X11.h"
5#include "evas_common_soft16.h"
6
7int _evas_engine_soft16_x11_log_dom = -1;
8/* function tables - filled in later (func and parent func) */
9static Evas_Func func, pfunc;
10/*
11struct xrdb_user
12{
13 time_t last_stat;
14 time_t last_mtime;
15 XrmDatabase db;
16};
17static struct xrdb_user xrdb_user = {0, 0, NULL};
18
19static Eina_Bool
20xrdb_user_query(const char *name, const char *cls, char **type, XrmValue *val)
21{
22 time_t last = xrdb_user.last_stat, now = time(NULL);
23
24 xrdb_user.last_stat = now;
25 if (last != now) // don't stat() more than once every second
26 {
27 struct stat st;
28 const char *home = getenv("HOME");
29 char tmp[PATH_MAX];
30
31 if (!home) goto failed;
32 snprintf(tmp, sizeof(tmp), "%s/.Xdefaults", home);
33 if (stat(tmp, &st) != 0) goto failed;
34 if (xrdb_user.last_mtime != st.st_mtime)
35 {
36 if (xrdb_user.db) XrmDestroyDatabase(xrdb_user.db);
37 xrdb_user.db = XrmGetFileDatabase(tmp);
38 if (!xrdb_user.db) goto failed;
39 xrdb_user.last_mtime = st.st_mtime;
40 }
41 }
42
43 if (!xrdb_user.db) return EINA_FALSE;
44 return XrmGetResource(xrdb_user.db, name, cls, type, val);
45
46 failed:
47 if (xrdb_user.db)
48 {
49 XrmDestroyDatabase(xrdb_user.db);
50 xrdb_user.db = NULL;
51 }
52 xrdb_user.last_mtime = 0;
53 return EINA_FALSE;
54}
55*/
56
57/* engine struct data */
58typedef struct _Render_Engine Render_Engine;
59
60struct _Render_Engine
61{
62 Display *disp;
63 Drawable draw;
64 GC gc;
65 int w, h, rot;
66 Tilebuf *tb;
67 Tilebuf_Rect *rects;
68 Tilebuf_Rect *cur_rect;
69/*
70 XrmDatabase xrdb; // xres - dpi
71 struct { // xres - dpi
72 int dpi; // xres - dpi
73 } xr; // xres - dpi
74 */
75 X_Output_Buffer *shbuf;
76 Soft16_Image *tmp_out; /* used by indirect render, like rotation */
77 Region clip_rects;
78 unsigned char end : 1;
79 unsigned char shm : 1;
80};
81
82/* prototypes we will use here */
83
84static void *eng_info(Evas *e);
85static void eng_info_free(Evas *e, void *info);
86static int eng_setup(Evas *e, void *info);
87static void eng_output_free(void *data);
88static void eng_output_resize(void *data, int w, int h);
89static void eng_output_tile_size_set(void *data, int w, int h);
90static void eng_output_redraws_rect_add(void *data, int x, int y, int w, int h);
91static void eng_output_redraws_rect_del(void *data, int x, int y, int w, int h);
92static void eng_output_redraws_clear(void *data);
93static void *eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, int *cx, int *cy, int *cw, int *ch);
94static void eng_output_redraws_next_update_push(void *data, void *surface, int x, int y, int w, int h);
95static void eng_output_flush(void *data);
96static void eng_output_idle_flush(void *data);
97
98/* engine api this module provides */
99static void *
100eng_info(Evas *e)
101{
102 Evas_Engine_Info_Software_16_X11 *info;
103
104 info = calloc(1, sizeof(Evas_Engine_Info_Software_16_X11));
105 if (!info) return NULL;
106 info->magic.magic = rand();
107 info->render_mode = EVAS_RENDER_MODE_BLOCKING;
108 return info;
109 e = NULL;
110}
111
112static void
113eng_info_free(Evas *e __UNUSED__, void *info)
114{
115 Evas_Engine_Info_Software_16_X11 *in;
116 in = (Evas_Engine_Info_Software_16_X11 *)info;
117 free(in);
118}
119
120static void
121_tmp_out_alloc(Render_Engine *re)
122{
123 Tilebuf_Rect *r;
124 unsigned int w = 0, h = 0;
125
126 EINA_INLIST_FOREACH(re->rects, r)
127 {
128 if (r->w > (int)w) w = r->w;
129 if (r->h > (int)h) h = r->h;
130 }
131
132 if (re->tmp_out)
133 {
134 if ((re->tmp_out->cache_entry.w < w) || (re->tmp_out->cache_entry.h < h))
135 {
136 evas_cache_image_drop(&re->tmp_out->cache_entry);
137 re->tmp_out = NULL;
138 }
139 }
140
141 if (!re->tmp_out)
142 {
143 Soft16_Image *im;
144
145 im = (Soft16_Image *) evas_cache_image_empty(evas_common_soft16_image_cache_get());
146 im->cache_entry.flags.alpha = 0;
147 evas_cache_image_surface_alloc(&im->cache_entry, w, h);
148
149 re->tmp_out = im;
150 }
151}
152
153
154static int
155eng_setup(Evas *e, void *in)
156{
157 Render_Engine *re;
158 Evas_Engine_Info_Software_16_X11 *info;
159/* X_Output_Buffer *xob; */
160 XGCValues gcv;
161
162 info = (Evas_Engine_Info_Software_16_X11 *)in;
163 if (!e->engine.data.output)
164 {
165 /* the only check - simplistic, i know, but enough for this
166 * "special purpose" engine. Remember it is meant to be used
167 * for limited power devices that have a 16bit display mode
168 * and no real other acceleration, and high resolution so we
169 * can pre-dither into 16bpp. */
170// if (DefaultDepth(info->info.display,
171// DefaultScreen(info->info.display)) != 16)
172// return;
173 /* do common routine init - we wil at least use it for core
174 * image loading and font loading/glyph rendering & placement */
175 evas_common_cpu_init();
176
177 evas_common_blend_init();
178 evas_common_image_init();
179 evas_common_convert_init();
180 evas_common_scale_init();
181 evas_common_rectangle_init();
182 evas_common_polygon_init();
183 evas_common_line_init();
184 evas_common_font_init();
185 evas_common_draw_init();
186 evas_common_tilebuf_init();
187 evas_common_soft16_image_init();
188
189 /* render engine specific data */
190 re = calloc(1, sizeof(Render_Engine));
191 if (!re)
192 return 0;
193 e->engine.data.output = re;
194 re->disp = info->info.display;
195 re->draw = info->info.drawable;
196 re->gc = XCreateGC(re->disp, re->draw, 0, &gcv);
197 re->w = e->output.w;
198 re->h = e->output.h;
199 re->rot = info->info.rotation;
200 re->tb = evas_common_tilebuf_new(e->output.w, e->output.h);
201 if (re->tb)
202 evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE);
203 }
204 else
205 {
206 /* we changed the info after first init - do a re-eval where
207 * appropriate */
208// if (DefaultDepth(info->info.display,
209// DefaultScreen(info->info.display)) != 16)
210// return;
211 re = e->engine.data.output;
212 if (re->tb) evas_common_tilebuf_free(re->tb);
213 re->disp = info->info.display;
214 re->draw = info->info.drawable;
215 XFreeGC(re->disp, re->gc);
216 re->gc = XCreateGC(re->disp, re->draw, 0, &gcv);
217 re->w = e->output.w;
218 re->h = e->output.h;
219 re->rot = info->info.rotation;
220 re->tb = evas_common_tilebuf_new(e->output.w, e->output.h);
221 if (re->tb)
222 evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE);
223 if (re->tmp_out)
224 {
225 evas_cache_image_drop(&re->tmp_out->cache_entry);
226 re->tmp_out = NULL;
227 }
228 }
229 if (!e->engine.data.output) return 0;
230
231/*
232 {
233 int status;
234 char *type = NULL;
235 XrmValue val;
236
237 re->xr.dpi = 75000; // dpy * 1000
238
239 status = xrdb_user_query("Xft.dpi", "Xft.Dpi", &type, &val);
240 if ((!status) || (!type))
241 {
242 if (!re->xrdb) re->xrdb = XrmGetDatabase(re->disp);
243 if (re->xrdb)
244 status = XrmGetResource(re->xrdb,
245 "Xft.dpi", "Xft.Dpi", &type, &val);
246 }
247
248 if ((status) && (type))
249 {
250 if (!strcmp(type, "String"))
251 {
252 const char *str, *dp;
253
254 str = val.addr;
255 dp = strchr(str, '.');
256 if (!dp) dp = strchr(str, ',');
257
258 if (dp)
259 {
260 int subdpi, len, i;
261 char *buf;
262
263 buf = alloca(dp - str + 1);
264 strncpy(buf, str, dp - str);
265 buf[dp - str] = 0;
266 len = strlen(dp + 1);
267 subdpi = atoi(dp + 1);
268
269 if (len < 3)
270 {
271 for (i = len; i < 3; i++) subdpi *= 10;
272 }
273 else if (len > 3)
274 {
275 for (i = len; i > 3; i--) subdpi /= 10;
276 }
277 re->xr.dpi = atoi(buf) * 1000;
278 }
279 else
280 re->xr.dpi = atoi(str) * 1000;
281 }
282 }
283 evas_common_font_dpi_set(re->xr.dpi / 1000);
284 }
285 */
286
287 /* add a draw context if we dont have one */
288 if (!e->engine.data.context)
289 e->engine.data.context =
290 e->engine.func->context_new(e->engine.data.output);
291 /* check if the display can do shm */
292 re->shm = evas_software_16_x11_x_can_do_shm(re->disp);
293
294 return 1;
295}
296
297static void
298eng_output_free(void *data)
299{
300 Render_Engine *re;
301
302 re = (Render_Engine *)data;
303
304// NOTE: XrmGetDatabase() result is shared per connection, do not free it.
305// if (re->xrdb) XrmDestroyDatabase(re->xrdb);
306
307 if (re->shbuf) evas_software_16_x11_x_output_buffer_free(re->shbuf, 0);
308 if (re->clip_rects) XDestroyRegion(re->clip_rects);
309 if (re->gc) XFreeGC(re->disp, re->gc);
310 if (re->tb) evas_common_tilebuf_free(re->tb);
311 if (re->rects) evas_common_tilebuf_free_render_rects(re->rects);
312 if (re->tmp_out) evas_cache_image_drop(&re->tmp_out->cache_entry);
313 free(re);
314
315 evas_common_font_shutdown();
316 evas_common_image_shutdown();
317 evas_common_soft16_image_shutdown();
318}
319
320static void
321eng_output_resize(void *data, int w, int h)
322{
323 Render_Engine *re;
324
325 re = (Render_Engine *)data;
326
327 if ((re->w == w) && (re->h == h)) return;
328
329 evas_common_tilebuf_free(re->tb);
330 re->w = w;
331 re->h = h;
332 re->tb = evas_common_tilebuf_new(w, h);
333 if (re->tb)
334 evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE);
335 if (re->shbuf)
336 {
337 evas_software_16_x11_x_output_buffer_free(re->shbuf, 0);
338 re->shbuf = NULL;
339 }
340 if (re->clip_rects)
341 {
342 XDestroyRegion(re->clip_rects);
343 re->clip_rects = NULL;
344 }
345 if (re->tmp_out)
346 {
347 evas_cache_image_drop(&re->tmp_out->cache_entry);
348 re->tmp_out = NULL;
349 }
350}
351
352static void
353eng_output_tile_size_set(void *data, int w, int h)
354{
355 Render_Engine *re;
356
357 re = (Render_Engine *)data;
358 evas_common_tilebuf_set_tile_size(re->tb, w, h);
359}
360
361static void
362eng_output_redraws_rect_add(void *data, int x, int y, int w, int h)
363{
364 Render_Engine *re;
365
366 re = (Render_Engine *)data;
367 evas_common_tilebuf_add_redraw(re->tb, x, y, w, h);
368}
369
370static void
371eng_output_redraws_rect_del(void *data, int x, int y, int w, int h)
372{
373 Render_Engine *re;
374
375 re = (Render_Engine *)data;
376 evas_common_tilebuf_del_redraw(re->tb, x, y, w, h);
377}
378
379static void
380eng_output_redraws_clear(void *data)
381{
382 Render_Engine *re;
383
384 re = (Render_Engine *)data;
385 evas_common_tilebuf_clear(re->tb);
386}
387
388static inline void
389_output_buffer_alloc(Render_Engine *re)
390{
391 int w, h;
392 if (re->shbuf) return;
393
394 if ((re->rot == 0) || (re->rot == 180))
395 {
396 w = re->w;
397 h = re->h;
398 }
399 else
400 {
401 w = re->h;
402 h = re->w;
403 }
404
405 re->shbuf = evas_software_16_x11_x_output_buffer_new
406 (re->disp, DefaultVisual(re->disp, DefaultScreen(re->disp)),
407 DefaultDepth(re->disp, DefaultScreen(re->disp)),
408 w, h, 1, NULL);
409}
410
411static void *
412eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, int *cx, int *cy, int *cw, int *ch)
413{
414 Render_Engine *re;
415 Tilebuf_Rect *rect;
416 int ux, uy, uw, uh;
417
418 re = (Render_Engine *)data;
419 if (re->end)
420 {
421 re->end = 0;
422 return NULL;
423 }
424 if (!re->rects)
425 {
426 re->rects = evas_common_tilebuf_get_render_rects(re->tb);
427 if (!re->rects) return NULL;
428
429 re->cur_rect = re->rects;
430 _output_buffer_alloc(re);
431 if (re->rot != 0) _tmp_out_alloc(re); /* grows if required */
432 }
433 if (!re->cur_rect)
434 {
435 if (re->rects) evas_common_tilebuf_free_render_rects(re->rects);
436 re->rects = NULL;
437 return NULL;
438 }
439 rect = re->cur_rect;
440 ux = rect->x; uy = rect->y; uw = rect->w; uh = rect->h;
441 re->cur_rect = (Tilebuf_Rect *)((EINA_INLIST_GET(re->cur_rect))->next);
442 if (!re->cur_rect)
443 {
444 evas_common_tilebuf_free_render_rects(re->rects);
445 re->rects = NULL;
446 re->end = 1;
447 }
448
449 *x = ux; *y = uy; *w = uw; *h = uh;
450 if (re->rot == 0)
451 {
452 *cx = ux; *cy = uy; *cw = uw; *ch = uh;
453 return re->shbuf->im;
454 }
455 else
456 {
457 *cx = 0; *cy = 0; *cw = uw; *ch = uh;
458 return re->tmp_out;
459 }
460}
461
462static void
463_blit_rot_90(Soft16_Image *dst, const Soft16_Image *src,
464 int out_x, int out_y, int w, int h)
465{
466 DATA16 *dp, *sp;
467 int x, y;
468
469 sp = src->pixels;
470 dp = dst->pixels + (out_x +
471 (w + out_y - 1) * dst->stride);
472
473 for (y = 0; y < h; y++)
474 {
475 DATA16 *dp_itr, *sp_itr;
476
477 sp_itr = sp;
478 dp_itr = dp;
479
480 for (x = 0; x < w; x++)
481 {
482 *dp_itr = *sp_itr;
483
484 sp_itr++;
485 dp_itr -= dst->stride;
486 }
487 sp += src->stride;
488 dp++;
489 }
490}
491
492static void
493_blit_rot_180(Soft16_Image *dst, const Soft16_Image *src,
494 int out_x, int out_y, int w, int h)
495{
496 DATA16 *dp, *sp;
497 int x, y;
498
499 sp = src->pixels;
500 dp = dst->pixels + ((w + out_x - 1) +
501 (h + out_y - 1) * dst->stride);
502
503 for (y = 0; y < h; y++)
504 {
505 DATA16 *dp_itr, *sp_itr;
506
507 sp_itr = sp;
508 dp_itr = dp;
509
510 for (x = 0; x < w; x++)
511 {
512 *dp_itr = *sp_itr;
513
514 sp_itr++;
515 dp_itr--;
516 }
517 sp += src->stride;
518 dp -= dst->stride;
519 }
520}
521
522static void
523_blit_rot_270(Soft16_Image *dst, const Soft16_Image *src,
524 int out_x, int out_y, int w, int h)
525{
526 DATA16 *dp, *sp;
527 int x, y;
528
529 sp = src->pixels;
530 dp = dst->pixels + ((h + out_x - 1) +
531 out_y * dst->stride);
532
533 for (y = 0; y < h; y++)
534 {
535 DATA16 *dp_itr, *sp_itr;
536
537 sp_itr = sp;
538 dp_itr = dp;
539
540 for (x = 0; x < w; x++)
541 {
542 *dp_itr = *sp_itr;
543
544 sp_itr++;
545 dp_itr += dst->stride;
546 }
547 sp += src->stride;
548 dp--;
549 }
550}
551
552static void
553_tmp_out_process(Render_Engine *re, int out_x, int out_y, int w, int h)
554{
555 Soft16_Image *d, *s;
556
557 d = re->shbuf->im;
558 s = re->tmp_out;
559
560 if ((w < 1) || (h < 1) ||
561 (out_x >= (int)d->cache_entry.w) || (out_y >= (int)d->cache_entry.h))
562 return;
563
564 if (re->rot == 90)
565 _blit_rot_90(d, s, out_x, out_y, w, h);
566 else if (re->rot == 180)
567 _blit_rot_180(d, s, out_x, out_y, w, h);
568 else if (re->rot == 270)
569 _blit_rot_270(d, s, out_x, out_y, w, h);
570}
571
572static void
573eng_output_redraws_next_update_push(void *data, void *surface __UNUSED__, int x, int y, int w, int h)
574{
575 Render_Engine *re;
576 XRectangle r = { 0, 0, 0, 0 };
577
578 re = (Render_Engine *)data;
579
580 if (!re->clip_rects)
581 re->clip_rects = XCreateRegion();
582
583 if (re->rot == 0)
584 {
585 r.x = x;
586 r.y = y;
587 r.width = w;
588 r.height = h;
589 }
590 else if (re->rot == 90)
591 {
592 r.x = y;
593 r.y = re->w - w - x;
594 r.width = h;
595 r.height = w;
596 }
597 else if (re->rot == 180)
598 {
599 r.x = re->w - w - x;
600 r.y = re->h - h - y;
601 r.width = w;
602 r.height = h;
603 }
604 else if (re->rot == 270)
605 {
606 r.x = re->h - h - y;
607 r.y = x;
608 r.width = h;
609 r.height = w;
610 }
611
612 if (re->rot != 0)
613 _tmp_out_process(re, r.x, r.y, w, h);
614 XUnionRectWithRegion(&r, re->clip_rects, re->clip_rects);
615}
616
617static void
618eng_output_flush(void *data)
619{
620 Render_Engine *re;
621
622 re = (Render_Engine *)data;
623 if (re->clip_rects)
624 {
625 XSetRegion(re->disp, re->gc, re->clip_rects);
626 XDestroyRegion(re->clip_rects);
627 re->clip_rects = NULL;
628 }
629 else return;
630
631 evas_software_16_x11_x_output_buffer_paste
632 (re->shbuf, re->draw, re->gc, 0, 0, re->shbuf->im->cache_entry.w, re->shbuf->im->cache_entry.h, 1);
633 XSetClipMask(re->disp, re->gc, None);
634}
635
636static void
637eng_output_idle_flush(void *data)
638{
639 Render_Engine *re;
640
641 re = (Render_Engine *)data;
642 if (re->shbuf)
643 {
644 evas_software_16_x11_x_output_buffer_free(re->shbuf, 0);
645 re->shbuf = NULL;
646 }
647 if (re->clip_rects)
648 {
649 XDestroyRegion(re->clip_rects);
650 re->clip_rects = NULL;
651 }
652 if (re->tmp_out)
653 {
654 evas_cache_image_drop(&re->tmp_out->cache_entry);
655 re->tmp_out = NULL;
656 }
657}
658
659static Eina_Bool
660eng_canvas_alpha_get(void *data __UNUSED__, void *context __UNUSED__)
661{
662 return EINA_FALSE;
663}
664
665/* module advertising code */
666static int
667module_open(Evas_Module *em)
668{
669 static Eina_Bool xrm_inited = EINA_FALSE;
670 if (!xrm_inited)
671 {
672 xrm_inited = EINA_TRUE;
673 XrmInitialize();
674 }
675
676 if (!em) return 0;
677 /* get whatever engine module we inherit from */
678 if (!_evas_module_engine_inherit(&pfunc, "software_16")) return 0;
679 _evas_engine_soft16_x11_log_dom = eina_log_domain_register
680 ("evas-software_16_x11", EVAS_DEFAULT_LOG_COLOR);
681 if (_evas_engine_soft16_x11_log_dom < 0)
682 {
683 EINA_LOG_ERR("Can not create a module log domain.");
684 return 0;
685 }
686
687 /* store it for later use */
688 func = pfunc;
689 /* now to override methods */
690#define ORD(f) EVAS_API_OVERRIDE(f, &func, eng_)
691 ORD(info);
692 ORD(info_free);
693 ORD(setup);
694 ORD(canvas_alpha_get);
695 ORD(output_free);
696 ORD(output_resize);
697 ORD(output_tile_size_set);
698 ORD(output_redraws_rect_add);
699 ORD(output_redraws_rect_del);
700 ORD(output_redraws_clear);
701 ORD(output_redraws_next_update_get);
702 ORD(output_redraws_next_update_push);
703 ORD(output_flush);
704 ORD(output_idle_flush);
705 /* now advertise out own api */
706 em->functions = (void *)(&func);
707 return 1;
708}
709
710static void
711module_close(Evas_Module *em __UNUSED__)
712{
713 eina_log_domain_unregister(_evas_engine_soft16_x11_log_dom);
714/*
715 if (xrdb_user.db)
716 {
717 XrmDestroyDatabase(xrdb_user.db);
718 xrdb_user.last_stat = 0;
719 xrdb_user.last_mtime = 0;
720 xrdb_user.db = NULL;
721 }
722 */
723}
724
725static Evas_Module_Api evas_modapi =
726{
727 EVAS_MODULE_API_VERSION,
728 "software_16_x11",
729 "none",
730 {
731 module_open,
732 module_close
733 }
734};
735
736EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_ENGINE, engine, software_16_x11);
737
738#ifndef EVAS_STATIC_BUILD_SOFTWARE_16_X11
739EVAS_EINA_MODULE_DEFINE(engine, software_16_x11);
740#endif
741