move around - flatter.
[profile/ivi/evas.git] / src / modules / engines / software_ddraw / evas_outbuf.c
1 #include "evas_common.h"
2 #include "evas_engine.h"
3
4
5 static Evas_List *ddpool = NULL;
6 static int ddsize = 0;
7 static int ddmemlimit = 10 * 1024 * 1024;
8 static int ddcountlimit = 32;
9
10 static DD_Output_Buffer *
11 _find_ddob(int depth, int w, int h, void *data)
12 {
13    Evas_List        *l;
14    Evas_List        *ddl;
15    DD_Output_Buffer *ddob = NULL;
16    int               sz;
17    int               lbytes;
18    int               bpp;
19
20    bpp = depth / 8;
21    if (bpp == 3) bpp = 4;
22    lbytes = (((w * bpp) + 3) / 4) * 4;
23    sz = lbytes * h;
24    for (l = ddpool; l; l = l->next)
25      {
26         DD_Output_Buffer *ddob2;
27
28         ddob2 = l->data;
29         if (ddob2->depth != depth)
30           continue;
31         if (ddob2->psize == sz)
32           {
33              ddob = ddob2;
34              ddl = l;
35              goto have_ddob;
36           }
37      }
38    if (!ddob)
39      return evas_software_ddraw_output_buffer_new(depth, w, h, data);
40
41    have_ddob:
42    ddpool = evas_list_remove_list(ddpool, ddl);
43    ddob->width = w;
44    ddob->height = h;
45    ddob->pitch = lbytes;
46    ddsize -= ddob->psize * (ddob->depth / 8);
47
48    return ddob;
49 }
50
51 static void
52 _unfind_ddob(DD_Output_Buffer *ddob)
53 {
54    ddpool = evas_list_prepend(ddpool, ddob);
55    ddsize += ddob->psize * ddob->depth / 8;
56    while ((ddsize > (ddmemlimit)) ||
57           (evas_list_count(ddpool) > ddcountlimit))
58      {
59         Evas_List *xl;
60
61         xl = evas_list_last(ddpool);
62         if (!xl)
63           {
64              ddsize = 0;
65              break;
66           }
67         ddob = xl->data;
68         ddpool = evas_list_remove_list(ddpool, xl);
69         evas_software_ddraw_output_buffer_free(ddob);
70      }
71 }
72
73 static void
74 _clear_ddob(int sync)
75 {
76    while (ddpool)
77      {
78         DD_Output_Buffer *ddob;
79
80         ddob = ddpool->data;
81         ddpool = evas_list_remove_list(ddpool, ddpool);
82         evas_software_ddraw_output_buffer_free(ddob);
83      }
84    ddsize = 0;
85 }
86
87 void
88 evas_software_ddraw_outbuf_init(void)
89 {
90 }
91
92 void
93 evas_software_ddraw_outbuf_free(Outbuf *buf)
94 {
95    if (!buf)
96      return;
97
98    evas_software_ddraw_shutdown(buf);
99    free(buf);
100 }
101
102 Outbuf *
103 evas_software_ddraw_outbuf_setup(int          width,
104                                  int          height,
105                                  int          rotation,
106                                  Outbuf_Depth depth,
107                                  HWND         window,
108                                  int          w_depth)
109 {
110    Outbuf *buf;
111
112    buf = (Outbuf *)calloc(1, sizeof(Outbuf));
113    if (!buf)
114       return NULL;
115
116    buf->width = width;
117    buf->height = height;
118    buf->depth = depth;
119    buf->rot = rotation;
120
121    if (!evas_software_ddraw_init(window, w_depth, buf))
122      {
123         free(buf);
124         return NULL;
125      }
126
127    {
128       Gfx_Func_Convert  conv_func;
129       DD_Output_Buffer *ddob;
130
131       ddob = evas_software_ddraw_output_buffer_new(w_depth, 1, 1, NULL);
132
133       conv_func = NULL;
134       if (ddob)
135         {
136            if (evas_software_ddraw_masks_get(buf))
137              {
138                 if ((rotation == 0) || (rotation == 180))
139                   conv_func = evas_common_convert_func_get(0,
140                                                            width,
141                                                            height,
142                                                            evas_software_ddraw_output_buffer_depth (ddob),
143                                                            buf->priv.mask.r,
144                                                            buf->priv.mask.g,
145                                                            buf->priv.mask.b,
146                                                            PAL_MODE_NONE,
147                                                            rotation);
148                 else if ((rotation == 90) || (rotation == 270))
149                   conv_func = evas_common_convert_func_get(0,
150                                                            height,
151                                                            width,
152                                                            evas_software_ddraw_output_buffer_depth (ddob),
153                                                            buf->priv.mask.r,
154                                                            buf->priv.mask.g,
155                                                            buf->priv.mask.b,
156                                                            PAL_MODE_NONE,
157                                                            rotation);
158              }
159
160            evas_software_ddraw_output_buffer_free(ddob);
161
162            if (!conv_func)
163              {
164                 fprintf(stderr, ".[ Evas Error ].\n"
165                         " {\n"
166                         "  At depth         %i:\n"
167                         "  RGB format mask: %08x, %08x, %08x\n"
168                         "  Not supported by and compiled in converters!\n"
169                         " }\n",
170                         buf->priv.dd.depth,
171                         buf->priv.mask.r,
172                         buf->priv.mask.g,
173                         buf->priv.mask.b);
174              }
175         }
176    }
177
178    return buf;
179 }
180
181 void
182 evas_software_ddraw_outbuf_reconfigure(Outbuf      *buf,
183                                        int          width,
184                                        int          height,
185                                        int          rotation,
186                                        Outbuf_Depth depth)
187 {
188    if ((width == buf->width) && (height == buf->height) &&
189        (rotation == buf->rot) && (depth == buf->depth))
190      return;
191    buf->width = width;
192    buf->height = height;
193    buf->rot = rotation;
194    evas_software_ddraw_surface_resize(buf);
195 }
196
197 RGBA_Image *
198 evas_software_ddraw_outbuf_new_region_for_update(Outbuf *buf,
199                                                  int     x,
200                                                  int     y,
201                                                  int     w,
202                                                  int     h,
203                                                  int    *cx,
204                                                  int    *cy,
205                                                  int    *cw,
206                                                  int    *ch)
207 {
208    RGBA_Image    *im;
209    Outbuf_Region *obr;
210    int            bpl = 0;
211    int            alpha = 0;
212
213    obr = calloc(1, sizeof(Outbuf_Region));
214    obr->x = x;
215    obr->y = y;
216    obr->width = w;
217    obr->height = h;
218    *cx = 0;
219    *cy = 0;
220    *cw = w;
221    *ch = h;
222
223    if ((buf->rot == 0) &&
224        (buf->priv.mask.r == 0xff0000) &&
225        (buf->priv.mask.g == 0x00ff00) &&
226        (buf->priv.mask.b == 0x0000ff))
227      {
228         obr->ddob = _find_ddob(buf->priv.dd.depth, w, h, NULL);
229 /*      obr->ddob = evas_software_x11_x_output_buffer_new(buf->priv.dd.disp, */
230 /*                                                         buf->priv.dd.vis, */
231 /*                                                         buf->priv.dd.depth, */
232 /*                                                         w, h, */
233 /*                                                         use_shm, */
234 /*                                                         NULL); */
235         im = (RGBA_Image *)evas_cache_image_data(evas_common_image_cache_get(),
236                                                  w, h,
237                                                  (DATA32 *) evas_software_ddraw_output_buffer_data(obr->ddob, &bpl),
238                                                  alpha, EVAS_COLORSPACE_ARGB8888);
239         im->extended_info = obr;
240      }
241    else
242      {
243         im = (RGBA_Image *) evas_cache_image_empty(evas_common_image_cache_get());
244         im->cache_entry.flags.alpha |= alpha ? 1 : 0;
245         evas_cache_image_surface_alloc(&im->cache_entry, w, h);
246         im->extended_info = obr;
247         if ((buf->rot == 0) || (buf->rot == 180))
248           obr->ddob = _find_ddob(buf->priv.dd.depth, w, h, NULL);
249 /*
250           obr->ddob = evas_software_x11_x_output_buffer_new(buf->priv.dd.disp,
251                                                            buf->priv.dd.vis,
252                                                            buf->priv.dd.depth,
253                                                            w, h,
254                                                            use_shm,
255                                                            NULL);
256  */
257         else if ((buf->rot == 90) || (buf->rot == 270))
258           obr->ddob = _find_ddob(buf->priv.dd.depth, h, w, NULL);
259 /*
260           obr->ddob = evas_software_x11_x_output_buffer_new(buf->priv.dd.disp,
261                                                            buf->priv.dd.vis,
262                                                            buf->priv.dd.depth,
263                                                            h, w,
264                                                            use_shm,
265                                                            NULL);
266  */
267      }
268
269    buf->priv.pending_writes = evas_list_append(buf->priv.pending_writes, im);
270    return im;
271 }
272
273 void
274 evas_software_ddraw_outbuf_push_updated_region(Outbuf     *buf,
275                                                RGBA_Image *update,
276                                                int        x,
277                                                int        y,
278                                                int        w,
279                                                int        h)
280 {
281    Gfx_Func_Convert    conv_func;
282    Outbuf_Region      *obr;
283    DATA32             *src_data;
284    void               *data;
285    int                 bpl = 0, yy;
286
287    conv_func = NULL;
288    obr = update->extended_info;
289
290    if ((buf->rot == 0) || (buf->rot == 180))
291      conv_func = evas_common_convert_func_get(0, w, h,
292                                               evas_software_ddraw_output_buffer_depth(obr->ddob),
293                                               buf->priv.mask.r,
294                                               buf->priv.mask.g,
295                                               buf->priv.mask.b,
296                                               PAL_MODE_NONE,
297                                               buf->rot);
298    else if ((buf->rot == 90) || (buf->rot == 270))
299      conv_func = evas_common_convert_func_get(0, h, w,
300                                               evas_software_ddraw_output_buffer_depth(obr->ddob),
301                                               buf->priv.mask.r,
302                                               buf->priv.mask.g,
303                                               buf->priv.mask.b,
304                                               PAL_MODE_NONE, buf->rot);
305    if (!conv_func) return;
306
307    data = evas_software_ddraw_output_buffer_data(obr->ddob, &bpl);
308    src_data = update->image.data;
309    if (buf->rot == 0)
310      {
311         obr->x = x;
312         obr->y = y;
313      }
314    else if (buf->rot == 90)
315      {
316         obr->x = y;
317         obr->y = buf->width - x - w;
318      }
319    else if (buf->rot == 180)
320      {
321         obr->x = buf->width - x - w;
322         obr->y = buf->height - y - h;
323      }
324    else if (buf->rot == 270)
325      {
326         obr->x = buf->height - y - h;
327         obr->y = x;
328      }
329    if ((buf->rot == 0) || (buf->rot == 180))
330      {
331         obr->width = w;
332         obr->height = h;
333      }
334    else if ((buf->rot == 90) || (buf->rot == 270))
335      {
336         obr->width = h;
337         obr->height = w;
338      }
339
340    if (data != src_data)
341      conv_func(src_data, data,
342                0,
343                bpl / ((evas_software_ddraw_output_buffer_depth(obr->ddob) / 8)) - obr->width,
344                obr->width,
345                obr->height,
346                x,
347                y,
348                NULL);
349 }
350
351 void
352 evas_software_ddraw_outbuf_free_region_for_update(Outbuf     *buf,
353                                                   RGBA_Image *update)
354 {
355    /* no need to do anything - they are cleaned up on flush */
356 }
357
358 void
359 evas_software_ddraw_outbuf_flush(Outbuf *buf)
360 {
361    Evas_List *l;
362    void      *ddraw_data;
363    int        ddraw_width;
364    int        ddraw_height;
365    int        ddraw_pitch;
366    int        ddraw_depth;
367
368    /* lock the back surface */
369    if (!(ddraw_data = evas_software_ddraw_lock(buf,
370                                                &ddraw_width,
371                                                &ddraw_height,
372                                                &ddraw_pitch,
373                                                &ddraw_depth)))
374      goto free_images;
375
376    /* copy safely the images that need to be drawn onto the back surface */
377    for (l = buf->priv.pending_writes; l; l = l->next)
378      {
379         RGBA_Image       *im;
380         Outbuf_Region    *obr;
381         DD_Output_Buffer *ddob;
382
383         im = l->data;
384         obr = im->extended_info;
385         ddob = obr->ddob;
386         evas_software_ddraw_output_buffer_paste(ddob,
387                                                 ddraw_data,
388                                                 ddraw_width,
389                                                 ddraw_height,
390                                                 ddraw_pitch,
391                                                 ddraw_depth,
392                                                 obr->x,
393                                                 obr->y);
394      }
395
396    /* unlock the back surface and flip the surface */
397    evas_software_ddraw_unlock_and_flip(buf);
398
399  free_images:
400    while (buf->priv.prev_pending_writes)
401      {
402         RGBA_Image    *im;
403         Outbuf_Region *obr;
404
405         im = buf->priv.prev_pending_writes->data;
406         buf->priv.prev_pending_writes =
407           evas_list_remove_list(buf->priv.prev_pending_writes,
408                                 buf->priv.prev_pending_writes);
409         obr = im->extended_info;
410         evas_cache_image_drop((Image_Entry *)im);
411         if (obr->ddob) _unfind_ddob(obr->ddob);
412 /*
413              if (obr->ddob) evas_software_x11_x_output_buffer_free(obr->ddob);
414  */
415         free(obr);
416      }
417    buf->priv.prev_pending_writes = buf->priv.pending_writes;
418    buf->priv.pending_writes = NULL;
419
420    evas_common_cpu_end_opt();
421 }
422
423 void
424 evas_software_ddraw_outbuf_idle_flush(Outbuf *buf)
425 {
426    while (buf->priv.prev_pending_writes)
427      {
428         RGBA_Image *im;
429         Outbuf_Region *obr;
430
431         im = buf->priv.prev_pending_writes->data;
432         buf->priv.prev_pending_writes =
433           evas_list_remove_list(buf->priv.prev_pending_writes,
434                                 buf->priv.prev_pending_writes);
435         obr = im->extended_info;
436         evas_cache_image_drop((Image_Entry *)im);
437         if (obr->ddob) _unfind_ddob(obr->ddob);
438         free(obr);
439      }
440    _clear_ddob(0);
441 }
442
443 int
444 evas_software_ddraw_outbuf_width_get(Outbuf *buf)
445 {
446    return buf->width;
447 }
448
449 int
450 evas_software_ddraw_outbuf_height_get(Outbuf *buf)
451 {
452    return buf->height;
453 }
454
455 Outbuf_Depth
456 evas_software_ddraw_outbuf_depth_get(Outbuf *buf)
457 {
458    return buf->depth;
459 }
460
461 int
462 evas_software_ddraw_outbuf_rot_get(Outbuf *buf)
463 {
464    return buf->rot;
465 }