summaryrefslogtreecommitdiff
path: root/src/modules/evas/engines/software_gdi/evas_outbuf.c
diff options
context:
space:
mode:
authorVincent Torri <vincent.torri@gmail.com>2012-11-04 11:51:42 +0000
committerVincent Torri <vincent.torri@gmail.com>2012-11-04 11:51:42 +0000
commitc15e9c6575c3b5f39ded167dda5259de3de96151 (patch)
tree5115d7ae3620af24c2bc094cd062575af7adeda9 /src/modules/evas/engines/software_gdi/evas_outbuf.c
parenta5ac6a987caec5a7f7596a25d0a065b9cc94c50c (diff)
merge: and now Evas
I've tested make -j 3 install and it works nicely I've tested expedite with software and opengl xlib, and it works. Not tested other engines, so please report any problems (engines or other) on the ML. TODO: examples and tests, I'll add them later ISSUE: Eina_Unicode size check. It indirectly depends on eina_config.h, which is created at the end of the configure script. So its size is always 0. I don't know how that size is used, so I can't do a lot, for now. SVN revision: 78895
Diffstat (limited to 'src/modules/evas/engines/software_gdi/evas_outbuf.c')
-rw-r--r--src/modules/evas/engines/software_gdi/evas_outbuf.c656
1 files changed, 656 insertions, 0 deletions
diff --git a/src/modules/evas/engines/software_gdi/evas_outbuf.c b/src/modules/evas/engines/software_gdi/evas_outbuf.c
new file mode 100644
index 0000000..87b3048
--- /dev/null
+++ b/src/modules/evas/engines/software_gdi/evas_outbuf.c
@@ -0,0 +1,656 @@
1#include "evas_common.h"
2#include "evas_engine.h"
3
4
5static Eina_List *gdipool = NULL;
6static int gdisize = 0;
7static int gdimemlimit = 10 * 1024 * 1024;
8static int gdicountlimit = 32;
9
10static Gdi_Output_Buffer *
11_find_gdiob(HDC dc, BITMAPINFO_GDI *bitmap_info, int depth, int w, int h, void *data)
12{
13 Eina_List *l = NULL;
14 Eina_List *gdil = NULL;
15 Gdi_Output_Buffer *gdiob = NULL;
16 Gdi_Output_Buffer *gdiob2;
17 int sz;
18 int lbytes;
19 int bpp;
20 int fitness = 0x7fffffff;
21
22 bpp = depth >> 3;
23 if (bpp == 3) bpp = 4;
24 lbytes = (((w * bpp) + 3) / 4) * 4;
25 sz = lbytes * h;
26 EINA_LIST_FOREACH(gdipool, l, gdiob2)
27 {
28 int szdif;
29
30 if ((gdiob2->dc != dc) ||
31 (gdiob2->bitmap_info != bitmap_info) ||
32 (gdiob2->depth != depth))
33 continue;
34 szdif = gdiob2->psize - sz;
35 if (szdif < 0) continue;
36 if (szdif == 0)
37 {
38 gdiob = gdiob2;
39 gdil = l;
40 goto have_gdiob;
41 }
42 if (szdif < fitness)
43 {
44 fitness = szdif;
45 gdiob = gdiob2;
46 gdil = l;
47 }
48 }
49 if ((fitness > (100 * 100)) || (!gdiob))
50 return evas_software_gdi_output_buffer_new(dc, bitmap_info, depth, w, h, data);
51
52 have_gdiob:
53 gdipool = eina_list_remove_list(gdipool, gdil);
54 gdiob->width = w;
55 gdiob->height = h;
56 gdiob->pitch = lbytes;
57 gdisize -= gdiob->psize * (gdiob->depth >> 3);
58
59 return gdiob;
60}
61
62static void
63_unfind_gdiob(Gdi_Output_Buffer *gdiob)
64{
65 gdipool = eina_list_prepend(gdipool, gdiob);
66 gdisize += gdiob->psize * (gdiob->depth >> 3);
67 while ((gdisize > (gdimemlimit)) ||
68 ((int)eina_list_count(gdipool) > gdicountlimit))
69 {
70 Eina_List *xl;
71
72 xl = eina_list_last(gdipool);
73 if (!xl)
74 {
75 gdisize = 0;
76 break;
77 }
78 gdiob = xl->data;
79 gdipool = eina_list_remove_list(gdipool, xl);
80 evas_software_gdi_output_buffer_free(gdiob);
81 }
82}
83
84static void
85_clear_gdiob()
86{
87 while (gdipool)
88 {
89 Gdi_Output_Buffer *gdiob;
90
91 gdiob = gdipool->data;
92 gdipool = eina_list_remove_list(gdipool, gdipool);
93 evas_software_gdi_output_buffer_free(gdiob);
94 }
95 gdisize = 0;
96}
97
98void
99evas_software_gdi_outbuf_init(void)
100{
101}
102
103void
104evas_software_gdi_outbuf_free(Outbuf *buf)
105{
106 if (!buf)
107 return;
108
109 while (buf->priv.pending_writes)
110 {
111 RGBA_Image *im;
112 Outbuf_Region *obr;
113
114 im = buf->priv.pending_writes->data;
115 buf->priv.pending_writes = eina_list_remove_list(buf->priv.pending_writes, buf->priv.pending_writes);
116 obr = im->extended_info;
117 evas_cache_image_drop(&im->cache_entry);
118 if (obr->gdiob) _unfind_gdiob(obr->gdiob);
119/* if (obr->mxob) _unfind_xob(obr->mxob, 0); */
120 free(obr);
121 }
122 evas_software_gdi_outbuf_idle_flush(buf);
123 evas_software_gdi_outbuf_flush(buf);
124
125 evas_software_gdi_shutdown(buf);
126 free(buf);
127}
128
129Outbuf *
130evas_software_gdi_outbuf_setup(int width,
131 int height,
132 int rotation,
133 Outbuf_Depth depth,
134 HWND window,
135 int w_depth,
136 unsigned int borderless,
137 unsigned int fullscreen,
138 unsigned int region,
139 int mask_dither,
140 int destination_alpha)
141{
142 Outbuf *buf;
143
144 buf = (Outbuf *)calloc(1, sizeof(Outbuf));
145 if (!buf)
146 return NULL;
147
148 buf->width = width;
149 buf->height = height;
150 buf->depth = depth;
151 buf->rot = rotation;
152
153 buf->priv.mask_dither = mask_dither;
154 buf->priv.destination_alpha = destination_alpha;
155
156 if (!evas_software_gdi_init(window, w_depth, borderless, fullscreen, region, buf))
157 {
158 free(buf);
159 return NULL;
160 }
161
162 {
163 Gfx_Func_Convert conv_func;
164 Gdi_Output_Buffer *gdiob;
165
166 gdiob = evas_software_gdi_output_buffer_new(buf->priv.gdi.dc, buf->priv.gdi.bitmap_info, w_depth, 1, 1, NULL);
167
168 conv_func = NULL;
169 if (gdiob)
170 {
171 if ((rotation == 0) || (rotation == 180))
172 conv_func = evas_common_convert_func_get(0,
173 width,
174 height,
175 evas_software_gdi_output_buffer_depth (gdiob),
176 buf->priv.gdi.bitmap_info->masks[0],
177 buf->priv.gdi.bitmap_info->masks[1],
178 buf->priv.gdi.bitmap_info->masks[2],
179 PAL_MODE_NONE,
180 rotation);
181 else if ((rotation == 90) || (rotation == 270))
182 conv_func = evas_common_convert_func_get(0,
183 height,
184 width,
185 evas_software_gdi_output_buffer_depth (gdiob),
186 buf->priv.gdi.bitmap_info->masks[0],
187 buf->priv.gdi.bitmap_info->masks[1],
188 buf->priv.gdi.bitmap_info->masks[2],
189 PAL_MODE_NONE,
190 rotation);
191
192 evas_software_gdi_output_buffer_free(gdiob);
193
194 if (!conv_func)
195 {
196 ERR(".[ soft_gdi engine Error ]."
197 " {"
198 " At depth %i:"
199 " RGB format mask: %08lx, %08lx, %08lx"
200 " Not supported by and compiled in converters!"
201 " }",
202 buf->priv.gdi.depth,
203 buf->priv.gdi.bitmap_info->masks[0],
204 buf->priv.gdi.bitmap_info->masks[1],
205 buf->priv.gdi.bitmap_info->masks[2]);
206 }
207 }
208 }
209
210 return buf;
211}
212
213void
214evas_software_gdi_outbuf_reconfigure(Outbuf *buf,
215 int width,
216 int height,
217 int rotation,
218 Outbuf_Depth depth)
219{
220 if ((width == buf->width) && (height == buf->height) &&
221 (rotation == buf->rot) && (depth == buf->depth))
222 return;
223 buf->width = width;
224 buf->height = height;
225 buf->rot = rotation;
226 evas_software_gdi_bitmap_resize(buf);
227 buf->priv.region_built = 0;
228}
229
230RGBA_Image *
231evas_software_gdi_outbuf_new_region_for_update(Outbuf *buf,
232 int x,
233 int y,
234 int w,
235 int h,
236 int *cx,
237 int *cy,
238 int *cw,
239 int *ch)
240{
241 RGBA_Image *im;
242 Outbuf_Region *obr;
243 int bpl = 0;
244 int alpha = 0;
245
246 obr = calloc(1, sizeof(Outbuf_Region));
247 obr->x = x;
248 obr->y = y;
249 obr->width = w;
250 obr->height = h;
251 *cx = 0;
252 *cy = 0;
253 *cw = w;
254 *ch = h;
255
256 alpha = ((buf->priv.gdi.region) || (buf->priv.destination_alpha));
257
258 if ((buf->rot == 0) &&
259 (buf->priv.gdi.bitmap_info->masks[0] == 0xff0000) &&
260 (buf->priv.gdi.bitmap_info->masks[1] == 0x00ff00) &&
261 (buf->priv.gdi.bitmap_info->masks[2] == 0x0000ff))
262 {
263 obr->gdiob = _find_gdiob(buf->priv.gdi.dc,
264 buf->priv.gdi.bitmap_info,
265 buf->priv.gdi.depth,
266 w, h, NULL);
267/* obr->gdiob = evas_software_gdi_output_buffer_new(buf->priv.gdi.dc, */
268/* buf->priv.gdi.bitmap_info, */
269/* buf->priv.gdi.depth, */
270/* w, h, */
271/* NULL); */
272 im = (RGBA_Image *)evas_cache_image_data(evas_common_image_cache_get(),
273 w, h,
274 (DATA32 *)evas_software_gdi_output_buffer_data(obr->gdiob, &bpl),
275 alpha, EVAS_COLORSPACE_ARGB8888);
276 im->extended_info = obr;
277/* if (buf->priv.gdi.mask) */
278/* obr->mgdiob = _find_gdiob(buf->priv.gdi.dc, */
279/* buf->priv.gdi.bitmap_info, */
280/* 1, */
281/* w, h, NULL); */
282 }
283 else
284 {
285 im = (RGBA_Image *) evas_cache_image_empty(evas_common_image_cache_get());
286 im->cache_entry.flags.alpha |= alpha ? 1 : 0;
287 evas_cache_image_surface_alloc(&im->cache_entry, w, h);
288 im->extended_info = obr;
289 if ((buf->rot == 0) || (buf->rot == 180))
290 obr->gdiob = _find_gdiob(buf->priv.gdi.dc,
291 buf->priv.gdi.bitmap_info,
292 buf->priv.gdi.depth,
293 w, h, NULL);
294/*
295 obr->gdiob = evas_software_x11_x_output_buffer_new(buf->priv.dd.disp,
296 buf->priv.dd.vis,
297 buf->priv.dd.depth,
298 w, h,
299 use_shm,
300 NULL);
301 */
302 else if ((buf->rot == 90) || (buf->rot == 270))
303 obr->gdiob = _find_gdiob(buf->priv.gdi.dc,
304 buf->priv.gdi.bitmap_info,
305 buf->priv.gdi.depth,
306 h, w, NULL);
307/*
308 obr->gdiob = evas_software_x11_x_output_buffer_new(buf->priv.dd.disp,
309 buf->priv.dd.vis,
310 buf->priv.dd.depth,
311 h, w,
312 use_shm,
313 NULL);
314 */
315/* if (buf->priv.gdi.mask) */
316/* obr->mgdiob = _find_gdiob(buf->priv.gdi.dc, */
317/* buf->priv.gdi.bitmap_info, */
318/* 1, */
319/* w, h, NULL); */
320 }
321 if ((buf->priv.gdi.region) || (buf->priv.destination_alpha))
322 /* FIXME: faster memset! */
323 memset(im->image.data, 0, w * h * sizeof(DATA32));
324
325 buf->priv.pending_writes = eina_list_append(buf->priv.pending_writes, im);
326 return im;
327}
328
329void
330evas_software_gdi_outbuf_push_updated_region(Outbuf *buf,
331 RGBA_Image *update,
332 int x,
333 int y,
334 int w,
335 int h)
336{
337 HRGN regions = NULL;
338 Gfx_Func_Convert conv_func;
339 Outbuf_Region *obr;
340 DATA32 *src_data;
341 void *data;
342 int bpl = 0;
343
344 conv_func = NULL;
345 obr = update->extended_info;
346
347 if ((buf->rot == 0) || (buf->rot == 180))
348 conv_func = evas_common_convert_func_get(0, w, h,
349 evas_software_gdi_output_buffer_depth(obr->gdiob),
350 buf->priv.gdi.bitmap_info->masks[0],
351 buf->priv.gdi.bitmap_info->masks[1],
352 buf->priv.gdi.bitmap_info->masks[2],
353 PAL_MODE_NONE,
354 buf->rot);
355 else if ((buf->rot == 90) || (buf->rot == 270))
356 conv_func = evas_common_convert_func_get(0, h, w,
357 evas_software_gdi_output_buffer_depth(obr->gdiob),
358 buf->priv.gdi.bitmap_info->masks[0],
359 buf->priv.gdi.bitmap_info->masks[1],
360 buf->priv.gdi.bitmap_info->masks[2],
361 PAL_MODE_NONE,
362 buf->rot);
363 if (!conv_func) return;
364
365 data = evas_software_gdi_output_buffer_data(obr->gdiob, &bpl);
366 src_data = update->image.data;
367 if (buf->rot == 0)
368 {
369 obr->x = x;
370 obr->y = y;
371 }
372 else if (buf->rot == 90)
373 {
374 obr->x = y;
375 obr->y = buf->width - x - w;
376 }
377 else if (buf->rot == 180)
378 {
379 obr->x = buf->width - x - w;
380 obr->y = buf->height - y - h;
381 }
382 else if (buf->rot == 270)
383 {
384 obr->x = buf->height - y - h;
385 obr->y = x;
386 }
387 if ((buf->rot == 0) || (buf->rot == 180))
388 {
389 obr->width = w;
390 obr->height = h;
391 }
392 else if ((buf->rot == 90) || (buf->rot == 270))
393 {
394 obr->width = h;
395 obr->height = w;
396 }
397
398 if (data != src_data)
399 conv_func(src_data, data,
400 0,
401 bpl / (evas_software_gdi_output_buffer_depth(obr->gdiob) >> 3) - obr->width,
402 obr->width,
403 obr->height,
404 x,
405 y,
406 NULL);
407
408 /* Region code */
409 if (!buf->priv.gdi.region)
410 {
411 if (buf->priv.gdi.regions)
412 DeleteObject(buf->priv.gdi.regions);
413 buf->priv.gdi.regions = NULL;
414 SetWindowRgn(buf->priv.gdi.window, NULL, 1);
415 return;
416 }
417
418 if (!buf->priv.region_built)
419 {
420 RECT rect;
421 POINT pt = { 0, 0 };
422 HRGN region;
423 DATA32 *tmp;
424 int i;
425 int j;
426 int ww;
427 int wh;
428 int dx;
429 int dy;
430 int xmin;
431 int xmax;
432
433 if (!GetClientRect(buf->priv.gdi.window, &rect))
434 return;
435
436 ww = rect.right - rect.left;
437 wh = rect.bottom - rect.top;
438
439 if (!GetWindowRect(buf->priv.gdi.window, &rect))
440 return;
441 if (!ClientToScreen(buf->priv.gdi.window, &pt))
442 return;
443 dx = x + pt.x - rect.left;
444 dy = y + pt.y - rect.top;
445
446 tmp = src_data;
447
448 for (j = 0; j < h; j++)
449 {
450 i = 0;
451 while (i < w)
452 {
453 if ((*tmp & 0xff000000) == 0xff000000)
454 {
455 xmin = dx + i;
456 if ((i + 1) == w)
457 {
458 xmax = dx + i;
459 region = CreateRectRgn(xmin, dy + j, xmax + 1, dy + j + 1);
460 if (regions == NULL)
461 regions = region;
462 else
463 {
464 CombineRgn(regions, regions, region, RGN_OR);
465 DeleteObject(region);
466 }
467 }
468 else
469 {
470 i++;
471 tmp++;
472
473 while (i < w)
474 {
475 if ((*tmp & 0xff000000) == 0xff000000)
476 {
477 if ((i + 1) == w)
478 {
479 xmax = dx + i;
480 region = CreateRectRgn(xmin, dy + j, xmax + 1, dy + j + 1);
481 if (regions == NULL)
482 regions = region;
483 else
484 {
485 CombineRgn(regions, regions, region, RGN_OR);
486 DeleteObject(region);
487 }
488 break;
489 }
490 }
491 else
492 {
493 xmax = dx + i - 1;
494 region = CreateRectRgn(xmin, dy + j, xmax + 1, dy + j + 1);
495 if (regions == NULL)
496 regions = region;
497 else
498 {
499 CombineRgn(regions, regions, region, RGN_OR);
500 DeleteObject(region);
501 }
502 break;
503 }
504 i++;
505 tmp++;
506 }
507 }
508 }
509 i++;
510 tmp++;
511 }
512 }
513
514 if (!buf->priv.gdi.borderless)
515 {
516 RECT rnc;
517 RECT rc;
518 POINT pt = { 0, 0 };
519 LONG ncw;
520 LONG nch;
521 LONG cw;
522 LONG ch;
523
524 if (!GetWindowRect(buf->priv.gdi.window, &rnc))
525 return;
526 if (!GetClientRect(buf->priv.gdi.window, &rc))
527 return;
528 if (!ClientToScreen(buf->priv.gdi.window, &pt))
529 return;
530
531 ncw = rnc.right - rnc.left;
532 nch = rnc.bottom - rnc.top;
533 cw = rc.right - rc.left;
534 ch = rc.bottom - rc.top;
535
536 region = CreateRectRgn(0, 0, ncw, pt.y - rnc.top);
537 if (!regions)
538 regions = region;
539 else
540 {
541 CombineRgn(regions, regions, region, RGN_OR);
542 DeleteObject(region);
543 }
544 region = CreateRectRgn(0, pt.y - rnc.top, pt.x - rnc.left, nch);
545 CombineRgn(regions, regions, region, RGN_OR);
546 DeleteObject(region);
547 region = CreateRectRgn(pt.x - rnc.left, pt.y - rnc.top + ch, pt.x - rnc.left + cw, nch);
548 CombineRgn(regions, regions, region, RGN_OR);
549 DeleteObject(region);
550 region = CreateRectRgn(pt.x - rnc.left + cw, pt.y - rnc.top, ncw, nch);
551 CombineRgn(regions, regions, region, RGN_OR);
552 DeleteObject(region);
553 }
554
555 if (regions)
556 SetWindowRgn(buf->priv.gdi.window, regions, 1);
557 buf->priv.gdi.regions = regions;
558
559 buf->priv.region_built = 1;
560 }
561}
562
563void
564evas_software_gdi_outbuf_free_region_for_update(Outbuf *buf EINA_UNUSED,
565 RGBA_Image *update EINA_UNUSED)
566{
567 /* no need to do anything - they are cleaned up on flush */
568}
569
570void
571evas_software_gdi_outbuf_flush(Outbuf *buf)
572{
573 Eina_List *l;
574 RGBA_Image *im;
575 Outbuf_Region *obr;
576
577 /* copy safely the images that need to be drawn onto the back surface */
578 EINA_LIST_FOREACH(buf->priv.pending_writes, l, im)
579 {
580 Gdi_Output_Buffer *gdiob;
581
582 obr = im->extended_info;
583 gdiob = obr->gdiob;
584 evas_software_gdi_output_buffer_paste(gdiob,
585 obr->x,
586 obr->y);
587/* if (obr->mgdiob) */
588/* evas_software_gdi_output_buffer_paste(obr->mgdiob, */
589/* buf->priv.x11.xlib.mask, */
590/* buf->priv.x11.xlib.gcm, */
591/* obr->x, obr->y, 0); */
592 }
593
594 while (buf->priv.prev_pending_writes)
595 {
596 im = buf->priv.prev_pending_writes->data;
597 buf->priv.prev_pending_writes =
598 eina_list_remove_list(buf->priv.prev_pending_writes,
599 buf->priv.prev_pending_writes);
600 obr = im->extended_info;
601 evas_cache_image_drop(&im->cache_entry);
602 if (obr->gdiob) _unfind_gdiob(obr->gdiob);
603/* if (obr->mgdiob) _unfind_gdiob(obr->mgdiob); */
604/* if (obr->gdiob) evas_software_x11_x_output_buffer_free(obr->gdiob); */
605 free(obr);
606 }
607 buf->priv.prev_pending_writes = buf->priv.pending_writes;
608 buf->priv.pending_writes = NULL;
609
610 evas_common_cpu_end_opt();
611}
612
613void
614evas_software_gdi_outbuf_idle_flush(Outbuf *buf)
615{
616 while (buf->priv.prev_pending_writes)
617 {
618 RGBA_Image *im;
619 Outbuf_Region *obr;
620
621 im = buf->priv.prev_pending_writes->data;
622 buf->priv.prev_pending_writes =
623 eina_list_remove_list(buf->priv.prev_pending_writes,
624 buf->priv.prev_pending_writes);
625 obr = im->extended_info;
626 evas_cache_image_drop((Image_Entry *)im);
627 if (obr->gdiob) _unfind_gdiob(obr->gdiob);
628/* if (obr->mxob) _unfind_xob(obr->mxob, 0); */
629 free(obr);
630 }
631 _clear_gdiob();
632}
633
634int
635evas_software_gdi_outbuf_width_get(Outbuf *buf)
636{
637 return buf->width;
638}
639
640int
641evas_software_gdi_outbuf_height_get(Outbuf *buf)
642{
643 return buf->height;
644}
645
646Outbuf_Depth
647evas_software_gdi_outbuf_depth_get(Outbuf *buf)
648{
649 return buf->depth;
650}
651
652int
653evas_software_gdi_outbuf_rot_get(Outbuf *buf)
654{
655 return buf->rot;
656}