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