aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/evas/src/modules/engines/software_gdi/evas_outbuf.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/evas/src/modules/engines/software_gdi/evas_outbuf.c')
-rw-r--r--libraries/evas/src/modules/engines/software_gdi/evas_outbuf.c656
1 files changed, 656 insertions, 0 deletions
diff --git a/libraries/evas/src/modules/engines/software_gdi/evas_outbuf.c b/libraries/evas/src/modules/engines/software_gdi/evas_outbuf.c
new file mode 100644
index 0000000..6841baa
--- /dev/null
+++ b/libraries/evas/src/modules/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 (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 int *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 __UNUSED__,
565 RGBA_Image *update __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}