1 #include "evas_common_private.h"
2 #include "evas_engine.h"
3 
4 void
evas_software_gdi_outbuf_init(void)5 evas_software_gdi_outbuf_init(void)
6 {
7 }
8 
9 void
evas_software_gdi_outbuf_free(Outbuf * buf)10 evas_software_gdi_outbuf_free(Outbuf *buf)
11 {
12    if (!buf)
13      return;
14 
15    while (buf->priv.pending_writes)
16      {
17 	RGBA_Image *im;
18 	Outbuf_Region *obr;
19 
20 	im = buf->priv.pending_writes->data;
21 	buf->priv.pending_writes = eina_list_remove_list(buf->priv.pending_writes, buf->priv.pending_writes);
22 	obr = im->extended_info;
23 	evas_cache_image_drop(&im->cache_entry);
24 	if (obr->gdiob)
25           evas_software_gdi_output_buffer_free(obr->gdiob);
26 /* 	if (obr->mxob) _unfind_xob(obr->mxob, 0); */
27 	free(obr);
28      }
29    evas_software_gdi_outbuf_idle_flush(buf);
30    evas_software_gdi_outbuf_flush(buf, NULL, NULL, MODE_FULL);
31 
32    evas_software_gdi_shutdown(buf);
33    free(buf);
34 }
35 
36 Outbuf *
evas_software_gdi_outbuf_setup(int width,int height,int rotation,HWND window,unsigned int borderless,unsigned int fullscreen,unsigned int region,int mask_dither,int destination_alpha)37 evas_software_gdi_outbuf_setup(int          width,
38                                int          height,
39                                int          rotation,
40                                HWND         window,
41                                unsigned int borderless,
42                                unsigned int fullscreen,
43                                unsigned int region,
44                                int          mask_dither,
45                                int          destination_alpha)
46 {
47    Outbuf *buf;
48 
49    buf = (Outbuf *)calloc(1, sizeof(Outbuf));
50    if (!buf)
51       return NULL;
52 
53    buf->width = width;
54    buf->height = height;
55    buf->rot = rotation;
56 
57    buf->priv.mask_dither = mask_dither;
58    buf->priv.destination_alpha = destination_alpha;
59 
60    if (!evas_software_gdi_init(window, borderless, fullscreen, region, buf))
61      {
62         free(buf);
63         return NULL;
64      }
65 
66    {
67       Gfx_Func_Convert  conv_func;
68       Gdi_Output_Buffer *gdiob;
69 
70       gdiob = evas_software_gdi_output_buffer_new(buf->priv.gdi.dc, buf->priv.gdi.bitmap_info, 1, 1, NULL);
71 
72       conv_func = NULL;
73       if (gdiob)
74         {
75            if ((rotation == 0) || (rotation == 180))
76              conv_func = evas_common_convert_func_get(0,
77                                                       width,
78                                                       height,
79                                                       32,
80                                                       buf->priv.gdi.bitmap_info->masks[0],
81                                                       buf->priv.gdi.bitmap_info->masks[1],
82                                                       buf->priv.gdi.bitmap_info->masks[2],
83                                                       PAL_MODE_NONE,
84                                                       rotation);
85            else if ((rotation == 90) || (rotation == 270))
86              conv_func = evas_common_convert_func_get(0,
87                                                       height,
88                                                       width,
89                                                       32,
90                                                       buf->priv.gdi.bitmap_info->masks[0],
91                                                       buf->priv.gdi.bitmap_info->masks[1],
92                                                       buf->priv.gdi.bitmap_info->masks[2],
93                                                       PAL_MODE_NONE,
94                                                       rotation);
95 
96            evas_software_gdi_output_buffer_free(gdiob);
97 
98            if (!conv_func)
99              {
100                 ERR(".[ soft_gdi engine Error ]."
101                       " {"
102                       "  At depth         32:"
103                       "  RGB format mask: %08lx, %08lx, %08lx"
104                       "  Not supported by and compiled in converters!"
105                       " }",
106                         buf->priv.gdi.bitmap_info->masks[0],
107                         buf->priv.gdi.bitmap_info->masks[1],
108                         buf->priv.gdi.bitmap_info->masks[2]);
109              }
110         }
111    }
112 
113    return buf;
114 }
115 
116 void
evas_software_gdi_outbuf_reconfigure(Outbuf * buf,int width,int height,int rotation,Outbuf_Depth depth EINA_UNUSED)117 evas_software_gdi_outbuf_reconfigure(Outbuf      *buf,
118                                      int          width,
119                                      int          height,
120                                      int          rotation,
121                                      Outbuf_Depth depth EINA_UNUSED)
122 {
123    if ((width == buf->width) && (height == buf->height) &&
124        (rotation == buf->rot))
125      return;
126    buf->width = width;
127    buf->height = height;
128    buf->rot = rotation;
129    evas_software_gdi_bitmap_resize(buf);
130    buf->priv.region_built = 0;
131 }
132 
133 void *
evas_software_gdi_outbuf_new_region_for_update(Outbuf * buf,int x,int y,int w,int h,int * cx,int * cy,int * cw,int * ch)134 evas_software_gdi_outbuf_new_region_for_update(Outbuf *buf,
135                                                int     x,
136                                                int     y,
137                                                int     w,
138                                                int     h,
139                                                int    *cx,
140                                                int    *cy,
141                                                int    *cw,
142                                                int    *ch)
143 {
144    RGBA_Image    *im;
145    Outbuf_Region *obr;
146    int            bpl = 0;
147    int            alpha = 0;
148 
149    obr = calloc(1, sizeof(Outbuf_Region));
150    obr->x = x;
151    obr->y = y;
152    obr->width = w;
153    obr->height = h;
154    *cx = 0;
155    *cy = 0;
156    *cw = w;
157    *ch = h;
158 
159    alpha = ((buf->priv.gdi.region) || (buf->priv.destination_alpha));
160 
161    if ((buf->rot == 0) &&
162        (buf->priv.gdi.bitmap_info->masks[0] == 0xff0000) &&
163        (buf->priv.gdi.bitmap_info->masks[1] == 0x00ff00) &&
164        (buf->priv.gdi.bitmap_info->masks[2] == 0x0000ff))
165      {
166         obr->gdiob = evas_software_gdi_output_buffer_new(buf->priv.gdi.dc,
167                                                          buf->priv.gdi.bitmap_info,
168                                                          w, h, NULL);
169         im = (RGBA_Image *)evas_cache_image_data(evas_common_image_cache_get(),
170                                                  w, h,
171                                                  (DATA32 *)evas_software_gdi_output_buffer_data(obr->gdiob, &bpl),
172                                                  alpha, EVAS_COLORSPACE_ARGB8888);
173         im->extended_info = obr;
174 /* 	if (buf->priv.gdi.mask) */
175 /* 	  obr->mgdiob = _find_gdiob(buf->priv.gdi.dc, */
176 /*                                     buf->priv.gdi.bitmap_info, */
177 /*                                     1, */
178 /*                                     w, h, NULL); */
179      }
180    else
181      {
182         im = (RGBA_Image *) evas_cache_image_empty(evas_common_image_cache_get());
183         im->cache_entry.flags.alpha |= alpha ? 1 : 0;
184         evas_cache_image_surface_alloc(&im->cache_entry, w, h);
185         im->extended_info = obr;
186         if ((buf->rot == 0) || (buf->rot == 180))
187           obr->gdiob = evas_software_gdi_output_buffer_new(buf->priv.gdi.dc,
188                                                            buf->priv.gdi.bitmap_info,
189                                                            w, h, NULL);
190         else if ((buf->rot == 90) || (buf->rot == 270))
191           obr->gdiob = evas_software_gdi_output_buffer_new(buf->priv.gdi.dc,
192                                                            buf->priv.gdi.bitmap_info,
193                                                            h, w, NULL);
194 /* 	if (buf->priv.gdi.mask) */
195 /* 	  obr->mgdiob = _find_gdiob(buf->priv.gdi.dc, */
196 /*                                     buf->priv.gdi.bitmap_info, */
197 /*                                     1, */
198 /*                                     w, h, NULL); */
199      }
200    if ((buf->priv.gdi.region) || (buf->priv.destination_alpha))
201      {
202         /* FIXME: faster memset! */
203         /* memset(im->image.data, 0, w * h * sizeof(DATA32)); */
204      }
205 
206    buf->priv.pending_writes = eina_list_append(buf->priv.pending_writes, im);
207    return im;
208 }
209 
210 void
evas_software_gdi_outbuf_push_updated_region(Outbuf * buf,RGBA_Image * update,int x,int y,int w,int h)211 evas_software_gdi_outbuf_push_updated_region(Outbuf     *buf,
212                                              RGBA_Image *update,
213                                              int         x,
214                                              int         y,
215                                              int         w,
216                                              int         h)
217 {
218    HRGN             regions = NULL;
219    Gfx_Func_Convert conv_func;
220    Outbuf_Region   *obr;
221    DATA32          *src_data;
222    void            *data;
223    int              bpl = 0;
224 
225    conv_func = NULL;
226    obr = update->extended_info;
227 
228    if ((buf->rot == 0) || (buf->rot == 180))
229      conv_func = evas_common_convert_func_get(0, w, h, 32,
230                                               buf->priv.gdi.bitmap_info->masks[0],
231                                               buf->priv.gdi.bitmap_info->masks[1],
232                                               buf->priv.gdi.bitmap_info->masks[2],
233                                               PAL_MODE_NONE,
234                                               buf->rot);
235    else if ((buf->rot == 90) || (buf->rot == 270))
236      conv_func = evas_common_convert_func_get(0, h, w, 32,
237                                               buf->priv.gdi.bitmap_info->masks[0],
238                                               buf->priv.gdi.bitmap_info->masks[1],
239                                               buf->priv.gdi.bitmap_info->masks[2],
240                                               PAL_MODE_NONE,
241                                               buf->rot);
242    if (!conv_func) return;
243 
244    data = evas_software_gdi_output_buffer_data(obr->gdiob, &bpl);
245    src_data = update->image.data;
246    if (buf->rot == 0)
247      {
248 	obr->x = x;
249 	obr->y = y;
250      }
251    else if (buf->rot == 90)
252      {
253 	obr->x = y;
254 	obr->y = buf->width - x - w;
255      }
256    else if (buf->rot == 180)
257      {
258 	obr->x = buf->width - x - w;
259 	obr->y = buf->height - y - h;
260      }
261    else if (buf->rot == 270)
262      {
263 	obr->x = buf->height - y - h;
264 	obr->y = x;
265      }
266    if ((buf->rot == 0) || (buf->rot == 180))
267      {
268 	obr->width = w;
269 	obr->height = h;
270      }
271    else if ((buf->rot == 90) || (buf->rot == 270))
272      {
273 	obr->width = h;
274 	obr->height = w;
275      }
276 
277    if (data != src_data)
278      conv_func(src_data, data,
279                0,
280                bpl / 4 - obr->width,
281                obr->width,
282                obr->height,
283                x,
284                y,
285                NULL);
286 
287    /* Region code */
288    if (!buf->priv.gdi.region)
289      {
290         if (buf->priv.gdi.regions)
291           DeleteObject(buf->priv.gdi.regions);
292         buf->priv.gdi.regions = NULL;
293         SetWindowRgn(buf->priv.gdi.window, NULL, 1);
294         return;
295      }
296 
297    if (!buf->priv.region_built)
298      {
299         RECT  rect;
300         POINT pt = { 0, 0 };
301         HRGN region;
302         DATA32 *tmp;
303         int i;
304         int j;
305         int dx;
306         int dy;
307         int xmin;
308         int xmax;
309 
310         if (!GetClientRect(buf->priv.gdi.window, &rect))
311           return;
312 
313         if (!GetWindowRect(buf->priv.gdi.window, &rect))
314           return;
315         if (!ClientToScreen(buf->priv.gdi.window, &pt))
316           return;
317         dx = x + pt.x - rect.left;
318         dy = y + pt.y - rect.top;
319 
320         tmp = src_data;
321 
322         for (j = 0; j < h; j++)
323           {
324              i = 0;
325              while (i < w)
326                {
327                   if ((*tmp & 0xff000000) == 0xff000000)
328                     {
329                        xmin = dx + i;
330                        if ((i + 1) == w)
331                          {
332                             xmax = dx + i;
333                             region = CreateRectRgn(xmin, dy + j, xmax + 1, dy + j + 1);
334                             if (regions == NULL)
335                               regions = region;
336                             else
337                               {
338                                  CombineRgn(regions, regions, region, RGN_OR);
339                                  DeleteObject(region);
340                               }
341                          }
342                        else
343                          {
344                             i++;
345                             tmp++;
346 
347                             while (i < w)
348                               {
349                                  if ((*tmp & 0xff000000) == 0xff000000)
350                                    {
351                                       if ((i + 1) == w)
352                                         {
353                                            xmax = dx + i;
354                                            region = CreateRectRgn(xmin, dy + j, xmax + 1, dy + j + 1);
355                                            if (regions == NULL)
356                                              regions = region;
357                                            else
358                                              {
359                                                 CombineRgn(regions, regions, region, RGN_OR);
360                                                 DeleteObject(region);
361                                              }
362                                            break;
363                                         }
364                                    }
365                                  else
366                                    {
367                                       xmax = dx + i - 1;
368                                       region = CreateRectRgn(xmin, dy + j, xmax + 1, dy + j + 1);
369                                       if (regions == NULL)
370                                         regions = region;
371                                       else
372                                         {
373                                            CombineRgn(regions, regions, region, RGN_OR);
374                                            DeleteObject(region);
375                                         }
376                                       break;
377                                    }
378                                  i++;
379                                  tmp++;
380                               }
381                          }
382                     }
383                   i++;
384                   tmp++;
385                }
386           }
387 
388         if (!buf->priv.gdi.borderless)
389           {
390             RECT rnc;
391             RECT rc;
392             POINT pt = { 0, 0 };
393             LONG ncw;
394             LONG nch;
395             LONG cw;
396             LONG ch;
397 
398             if (!GetWindowRect(buf->priv.gdi.window, &rnc))
399               return;
400             if (!GetClientRect(buf->priv.gdi.window, &rc))
401               return;
402             if (!ClientToScreen(buf->priv.gdi.window, &pt))
403               return;
404 
405             ncw = rnc.right - rnc.left;
406             nch = rnc.bottom - rnc.top;
407             cw = rc.right - rc.left;
408             ch = rc.bottom - rc.top;
409 
410             region = CreateRectRgn(0, 0, ncw, pt.y - rnc.top);
411             if (!regions)
412               regions = region;
413             else
414               {
415                  CombineRgn(regions, regions, region, RGN_OR);
416                  DeleteObject(region);
417               }
418             region = CreateRectRgn(0, pt.y - rnc.top, pt.x - rnc.left, nch);
419             CombineRgn(regions, regions, region, RGN_OR);
420             DeleteObject(region);
421             region = CreateRectRgn(pt.x - rnc.left, pt.y - rnc.top + ch, pt.x - rnc.left + cw, nch);
422             CombineRgn(regions, regions, region, RGN_OR);
423             DeleteObject(region);
424             region = CreateRectRgn(pt.x - rnc.left + cw, pt.y - rnc.top, ncw, nch);
425             CombineRgn(regions, regions, region, RGN_OR);
426             DeleteObject(region);
427           }
428 
429         if (regions)
430           SetWindowRgn(buf->priv.gdi.window, regions, 1);
431         buf->priv.gdi.regions = regions;
432 
433         buf->priv.region_built = 1;
434      }
435 }
436 
437 void
evas_software_gdi_outbuf_flush(Outbuf * buf,Tilebuf_Rect * surface_damage EINA_UNUSED,Tilebuf_Rect * buffer_damage EINA_UNUSED,Evas_Render_Mode render_mode)438 evas_software_gdi_outbuf_flush(Outbuf *buf, Tilebuf_Rect *surface_damage EINA_UNUSED, Tilebuf_Rect *buffer_damage EINA_UNUSED, Evas_Render_Mode render_mode)
439 {
440    Eina_List     *l;
441    RGBA_Image    *im;
442    Outbuf_Region *obr;
443 
444    if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) return;
445 
446    /* copy safely the images that need to be drawn onto the back surface */
447    EINA_LIST_FOREACH(buf->priv.pending_writes, l, im)
448      {
449 	Gdi_Output_Buffer *gdiob;
450 
451         obr = im->extended_info;
452         gdiob = obr->gdiob;
453         evas_software_gdi_output_buffer_paste(gdiob,
454                                               obr->x,
455                                               obr->y);
456 /*         if (obr->mgdiob) */
457 /*           evas_software_gdi_output_buffer_paste(obr->mgdiob, */
458 /*                                                 buf->priv.x11.xlib.mask, */
459 /*                                                 buf->priv.x11.xlib.gcm, */
460 /*                                                 obr->x, obr->y, 0); */
461      }
462 
463    while (buf->priv.prev_pending_writes)
464      {
465         im = buf->priv.prev_pending_writes->data;
466         buf->priv.prev_pending_writes =
467           eina_list_remove_list(buf->priv.prev_pending_writes,
468                                 buf->priv.prev_pending_writes);
469         obr = im->extended_info;
470         evas_cache_image_drop(&im->cache_entry);
471         if (obr->gdiob)
472           evas_software_gdi_output_buffer_free(obr->gdiob);
473 /*         if (obr->mgdiob) _unfind_gdiob(obr->mgdiob); */
474         free(obr);
475      }
476    buf->priv.prev_pending_writes = buf->priv.pending_writes;
477    buf->priv.pending_writes = NULL;
478 
479    evas_common_cpu_end_opt();
480 }
481 
482 void
evas_software_gdi_outbuf_idle_flush(Outbuf * buf)483 evas_software_gdi_outbuf_idle_flush(Outbuf *buf)
484 {
485    while (buf->priv.prev_pending_writes)
486      {
487         RGBA_Image *im;
488         Outbuf_Region *obr;
489 
490         im = buf->priv.prev_pending_writes->data;
491         buf->priv.prev_pending_writes =
492           eina_list_remove_list(buf->priv.prev_pending_writes,
493                                 buf->priv.prev_pending_writes);
494         obr = im->extended_info;
495         evas_cache_image_drop((Image_Entry *)im);
496         if (obr->gdiob)
497           evas_software_gdi_output_buffer_free(obr->gdiob);
498 /*         if (obr->mxob) _unfind_xob(obr->mxob, 0); */
499         free(obr);
500      }
501 }
502 
503 int
evas_software_gdi_outbuf_width_get(Outbuf * buf)504 evas_software_gdi_outbuf_width_get(Outbuf *buf)
505 {
506    return buf->width;
507 }
508 
509 int
evas_software_gdi_outbuf_height_get(Outbuf * buf)510 evas_software_gdi_outbuf_height_get(Outbuf *buf)
511 {
512    return buf->height;
513 }
514 
515 int
evas_software_gdi_outbuf_rot_get(Outbuf * buf)516 evas_software_gdi_outbuf_rot_get(Outbuf *buf)
517 {
518    return buf->rot;
519 }
520