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