0fa1842fe1d12225d062a3e44f0ce453fd75f347
[framework/uifw/evas.git] / src / modules / engines / buffer / evas_outbuf.c
1 #include "evas_common.h"
2 #include "evas_engine.h"
3
4 void
5 evas_buffer_outbuf_buf_init(void)
6 {
7 }
8
9 void
10 evas_buffer_outbuf_buf_free(Outbuf *buf)
11 {
12    if (buf->priv.back_buf)
13      {
14         evas_cache_image_drop(&buf->priv.back_buf->cache_entry);
15      }
16    free(buf);
17 }
18
19 Outbuf *
20 evas_buffer_outbuf_buf_setup_fb(int w, int h, Outbuf_Depth depth, void *dest, int dest_row_bytes, int use_color_key, DATA32 color_key, int alpha_level,
21                                 void * (*new_update_region) (int x, int y, int w, int h, int *row_bytes),
22                                 void   (*free_update_region) (int x, int y, int w, int h, void *data),
23                                 void * (*switch_buffer) (void *data, void *dest_buffer),
24                                 void *switch_data
25                                 )
26 {
27    Outbuf *buf;
28    
29    buf = calloc(1, sizeof(Outbuf));
30    if (!buf) return NULL;
31
32    buf->w = w;
33    buf->h = h;
34    buf->depth = depth;
35
36    buf->dest = dest;
37    buf->dest_row_bytes = dest_row_bytes;
38
39    buf->alpha_level = alpha_level;
40    buf->color_key = color_key;
41    buf->use_color_key = use_color_key;
42    buf->first_frame = 1;
43
44    buf->func.new_update_region = new_update_region;
45    buf->func.free_update_region = free_update_region;
46    buf->func.switch_buffer = switch_buffer;
47    buf->switch_data = switch_data;
48
49    if ((buf->depth == OUTBUF_DEPTH_ARGB_32BPP_8888_8888) &&
50        (buf->dest) && (buf->dest_row_bytes == (buf->w * sizeof(DATA32))))
51      {
52         memset(buf->dest, 0, h * buf->dest_row_bytes);
53         buf->priv.back_buf = (RGBA_Image *) evas_cache_image_data(evas_common_image_cache_get(),
54                                                                   w, h,
55                                                                   buf->dest,
56                                                                   1, EVAS_COLORSPACE_ARGB8888);
57      }
58    else if ((buf->depth == OUTBUF_DEPTH_RGB_32BPP_888_8888) &&
59        (buf->dest) && (buf->dest_row_bytes == (buf->w * sizeof(DATA32))))
60      {
61         buf->priv.back_buf = (RGBA_Image *) evas_cache_image_data(evas_common_image_cache_get(),
62                                                                   w, h,
63                                                                   buf->dest,
64                                                                   0, EVAS_COLORSPACE_ARGB8888);
65      }
66
67    return buf;
68 }
69
70 RGBA_Image *
71 evas_buffer_outbuf_buf_new_region_for_update(Outbuf *buf, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch)
72 {
73    RGBA_Image *im;
74
75    if (buf->priv.back_buf)
76      {
77         *cx = x; *cy = y; *cw = w; *ch = h;
78         return buf->priv.back_buf;
79      }
80    else
81      {
82         *cx = 0; *cy = 0; *cw = w; *ch = h;
83         im = (RGBA_Image *) evas_cache_image_empty(evas_common_image_cache_get());
84         if (im)
85           {
86              if (((buf->depth == OUTBUF_DEPTH_ARGB_32BPP_8888_8888)) ||
87                  ((buf->depth == OUTBUF_DEPTH_BGRA_32BPP_8888_8888)))
88                {
89                   im->cache_entry.flags.alpha = 1;
90                   im = (RGBA_Image *) evas_cache_image_size_set(&im->cache_entry, w, h);
91                }
92           }
93      }
94    return im;
95 }
96
97 void
98 evas_buffer_outbuf_buf_free_region_for_update(Outbuf *buf, RGBA_Image *update)
99 {
100    if (update != buf->priv.back_buf) evas_cache_image_drop(&update->cache_entry);
101 }
102
103 void
104 evas_buffer_outbuf_buf_switch_buffer(Outbuf *buf)
105 {
106    if (buf->func.switch_buffer)
107      {
108         buf->dest = buf->func.switch_buffer(buf->switch_data, buf->dest);
109         if (buf->priv.back_buf)
110           {
111              evas_cache_image_drop(&buf->priv.back_buf->cache_entry);
112              buf->priv.back_buf = (RGBA_Image *) evas_cache_image_data(evas_common_image_cache_get(),
113                                                                        buf->w, buf->h,
114                                                                        buf->dest,
115                                                                        buf->depth == OUTBUF_DEPTH_ARGB_32BPP_8888_8888 ? 1 : 0,
116                                                                        EVAS_COLORSPACE_ARGB8888);
117           }
118      }
119 }
120
121 void
122 evas_buffer_outbuf_buf_push_updated_region(Outbuf *buf, RGBA_Image *update, int x, int y, int w, int h)
123 {
124    /* copy update image to out buf & convert */
125    switch (buf->depth)
126      {
127       case OUTBUF_DEPTH_RGB_24BPP_888_888:
128         /* copy & pack into 24bpp - if colorkey is enabled... etc. */
129           {
130              DATA8 thresh;
131              int xx, yy;
132              int row_bytes;
133              DATA8 *dest;
134              DATA32 colorkey;
135              DATA32 *src;
136              DATA8 *dst;
137
138              colorkey = buf->color_key;
139              thresh = buf->alpha_level;
140              row_bytes = buf->dest_row_bytes;
141              dest = (DATA8 *)(buf->dest) + (y * row_bytes) + (x * 3);
142              if (buf->func.new_update_region)
143                {
144                   dest = buf->func.new_update_region(x, y, w, h, &row_bytes);
145                }
146              if (!dest) break;
147              if (buf->use_color_key)
148                {
149                   for (yy = 0; yy < h; yy++)
150                     {
151                        dst = dest + (yy * row_bytes);
152                        src = update->image.data + (yy * update->cache_entry.w);
153                        for (xx = 0; xx < w; xx++)
154                          {
155                             if (A_VAL(src) > thresh)
156                               {
157                                  *dst++ = R_VAL(src);
158                                  *dst++ = G_VAL(src);
159                                  *dst++ = B_VAL(src);
160                               }
161                             else
162                               {
163                                  *dst++ = R_VAL(&colorkey);
164                                  *dst++ = G_VAL(&colorkey);
165                                  *dst++ = B_VAL(&colorkey);
166                               }
167                             src++;
168                          }
169                     }
170                }
171              else
172                {
173                   for (yy = 0; yy < h; yy++)
174                     {
175                        dst = dest + (yy * row_bytes);
176                        src = update->image.data + (yy * update->cache_entry.w);
177                        for (xx = 0; xx < w; xx++)
178                          {
179                             *dst++ = R_VAL(src);
180                             *dst++ = G_VAL(src);
181                             *dst++ = B_VAL(src);
182                             src++;
183                          }
184                     }
185                }
186              if (buf->func.free_update_region)
187                {
188                   buf->func.free_update_region(x, y, w, h, dest);
189                }
190           }
191         break;
192       case OUTBUF_DEPTH_BGR_24BPP_888_888:
193         /* copy & pack into 24bpp - if colorkey is enabled... etc. */
194           {
195              DATA8 thresh;
196              int xx, yy;
197              int row_bytes;
198              DATA8 *dest;
199              DATA32 colorkey;
200              DATA32 *src;
201              DATA8 *dst;
202
203              colorkey = buf->color_key;
204              thresh = buf->alpha_level;
205              row_bytes = buf->dest_row_bytes;
206              dest = (DATA8 *)(buf->dest) + (y * row_bytes) + (x * 3);
207              if (buf->func.new_update_region)
208                {
209                   dest = buf->func.new_update_region(x, y, w, h, &row_bytes);
210                }
211              if (!dest) break;
212              if (buf->use_color_key)
213                {
214                   for (yy = 0; yy < h; yy++)
215                     {
216                        dst = dest + (yy * row_bytes);
217                        src = update->image.data + (yy * update->cache_entry.w);
218                        for (xx = 0; xx < w; xx++)
219                          {
220                             if (A_VAL(src) > thresh)
221                               {
222                                  *dst++ = B_VAL(src);
223                                  *dst++ = G_VAL(src);
224                                  *dst++ = R_VAL(src);
225                               }
226                             else
227                               {
228                                  *dst++ = B_VAL(&colorkey);
229                                  *dst++ = G_VAL(&colorkey);
230                                  *dst++ = R_VAL(&colorkey);
231                               }
232                             src++;
233                          }
234                     }
235                }
236              else
237                {
238                   for (yy = 0; yy < h; yy++)
239                     {
240                        dst = dest + (yy * row_bytes);
241                        src = update->image.data + (yy * update->cache_entry.w);
242                        for (xx = 0; xx < w; xx++)
243                          {
244                             *dst++ = B_VAL(src);
245                             *dst++ = G_VAL(src);
246                             *dst++ = R_VAL(src);
247                             src++;
248                          }
249                     }
250                }
251              if (buf->func.free_update_region)
252                {
253                   buf->func.free_update_region(x, y, w, h, dest);
254                }
255           }
256         break;
257       case OUTBUF_DEPTH_RGB_32BPP_888_8888:
258       case OUTBUF_DEPTH_ARGB_32BPP_8888_8888:
259           {
260              DATA32 *dest, *src, *dst;
261              int yy, row_bytes;
262
263              row_bytes = buf->dest_row_bytes;
264              dest = (DATA32 *)((DATA8 *)(buf->dest) + (y * row_bytes) + (x * 4));
265              if (buf->func.new_update_region)
266                {
267                   dest = buf->func.new_update_region(x, y, w, h, &row_bytes);
268                }
269              /* no need src == dest */
270              if (!buf->priv.back_buf)
271                {
272                   Gfx_Func_Copy func;
273                   
274                   func = evas_common_draw_func_copy_get(w, 0);
275                   if (func)
276                     {
277                        for (yy = 0; yy < h; yy++)
278                          {
279                             src = update->image.data + (yy * update->cache_entry.w);
280                             dst = (DATA32 *)((DATA8 *)(buf->dest) + ((y + yy) * row_bytes));
281                             func(src, dst, w);
282                          }
283                        
284                     }
285                }
286              if (buf->func.free_update_region)
287                {
288                   buf->func.free_update_region(x, y, w, h, dest);
289                }
290           }
291         break;
292       case OUTBUF_DEPTH_BGR_32BPP_888_8888:
293           {
294              DATA32 *src, *dst;
295              DATA8 *dest;
296              int xx, yy, row_bytes;
297              
298              row_bytes = buf->dest_row_bytes;
299              dest = (DATA8 *)(buf->dest) + (y * row_bytes) + (x * 4);
300              if (buf->func.new_update_region)
301                {
302                   dest = buf->func.new_update_region(x, y, w, h, &row_bytes);
303                }
304              for (yy = 0; yy < h; yy++)
305                {
306                   dst = (DATA32 *)(dest + (yy * row_bytes));
307                   src = update->image.data + (yy * update->cache_entry.w);
308                   for (xx = 0; xx < w; xx++)
309                     {
310                        A_VAL(dst) = B_VAL(src);
311                        R_VAL(dst) = G_VAL(src);
312                        G_VAL(dst) = R_VAL(src);
313                        dst++;
314                        src++;
315                     }
316                }
317              if (buf->func.free_update_region)
318                {
319                   buf->func.free_update_region(x, y, w, h, dest);
320                }
321          }
322         break;
323       case OUTBUF_DEPTH_BGRA_32BPP_8888_8888:
324           {
325              DATA32 *src, *dst;
326              DATA8 *dest;
327              int xx, yy, row_bytes;
328              
329              row_bytes = buf->dest_row_bytes;
330              dest = (DATA8 *)(buf->dest) + (y * row_bytes) + (x * 4);
331              if (buf->func.new_update_region)
332                {
333                   dest = buf->func.new_update_region(x, y, w, h, &row_bytes);
334                }
335              for (yy = 0; yy < h; yy++)
336                {
337                   dst = (DATA32 *)(dest + (yy * row_bytes));
338                   src = update->image.data + (yy * update->cache_entry.w);
339                   for (xx = 0; xx < w; xx++)
340                     {
341                        A_VAL(dst) = B_VAL(src);
342                        R_VAL(dst) = G_VAL(src);
343                        G_VAL(dst) = R_VAL(src);
344                        dst++;
345                        src++;
346                     }
347                }
348              if (buf->func.free_update_region)
349                {
350                   buf->func.free_update_region(x, y, w, h, dest);
351                }
352          }
353         break;
354       default:
355         break;
356      }
357 }