big patch from Samsung SAIT (Advanced research group) for async multi-frame
[framework/uifw/evas.git] / src / modules / engines / software_x11 / evas_xlib_buffer.c
1 #include "evas_common.h"
2
3 #include "evas_xlib_buffer.h"
4
5 static int _x_err = 0;
6
7 void
8 evas_software_xlib_x_write_mask_line(Outbuf *buf, X_Output_Buffer *xob, DATA32 *src, int w, int y)
9 {
10    int x;
11    DATA32 *src_ptr;
12    DATA8 *dst_ptr;
13    int bpl = 0;
14
15    src_ptr = src;
16    dst_ptr = evas_software_xlib_x_output_buffer_data(xob, &bpl);
17    dst_ptr = dst_ptr + (bpl * y);
18    w -= 7;
19    if (buf->priv.x11.xlib.bit_swap)
20      {
21         for (x = 0; x < w; x += 8)
22           {
23              *dst_ptr =
24                ((A_VAL(&(src_ptr[0])) >> 7) << 7) |
25                ((A_VAL(&(src_ptr[1])) >> 7) << 6) |
26                ((A_VAL(&(src_ptr[2])) >> 7) << 5) |
27                ((A_VAL(&(src_ptr[3])) >> 7) << 4) |
28                ((A_VAL(&(src_ptr[4])) >> 7) << 3) |
29                ((A_VAL(&(src_ptr[5])) >> 7) << 2) |
30                ((A_VAL(&(src_ptr[6])) >> 7) << 1) |
31                ((A_VAL(&(src_ptr[7])) >> 7) << 0);
32              src_ptr += 8;
33              dst_ptr++;
34           }
35      }
36    else
37      {
38         for (x = 0; x < w; x += 8)
39           {
40              *dst_ptr =
41                ((A_VAL(&(src_ptr[0])) >> 7) << 0) |
42                ((A_VAL(&(src_ptr[1])) >> 7) << 1) |
43                ((A_VAL(&(src_ptr[2])) >> 7) << 2) |
44                ((A_VAL(&(src_ptr[3])) >> 7) << 3) |
45                ((A_VAL(&(src_ptr[4])) >> 7) << 4) |
46                ((A_VAL(&(src_ptr[5])) >> 7) << 5) |
47                ((A_VAL(&(src_ptr[6])) >> 7) << 6) |
48                ((A_VAL(&(src_ptr[7])) >> 7) << 7);
49              src_ptr += 8;
50              dst_ptr++;
51           }
52      }
53    w += 7;
54    for (; x < w; x ++)
55      {
56         XPutPixel(xob->xim, x, y, A_VAL(src_ptr) >> 7);
57         src_ptr++;
58      }
59 }
60
61 void
62 evas_software_xlib_x_write_mask_line_rev(Outbuf *buf, X_Output_Buffer *xob, DATA32 *src, int w, int y)
63 {
64    int x;
65    DATA32 *src_ptr;
66    DATA8 *dst_ptr;
67    int bpl = 0;
68
69    src_ptr = src + w - 1;
70    dst_ptr = evas_software_xlib_x_output_buffer_data(xob, &bpl);
71    dst_ptr = dst_ptr + (bpl * y);
72    w -= 7;
73    if (buf->priv.x11.xlib.bit_swap)
74      {
75         for (x = 0; x < w; x += 8)
76           {
77              *dst_ptr =
78                ((A_VAL(&(src_ptr[ 0])) >> 7) << 7) |
79                ((A_VAL(&(src_ptr[-1])) >> 7) << 6) |
80                ((A_VAL(&(src_ptr[-2])) >> 7) << 5) |
81                ((A_VAL(&(src_ptr[-3])) >> 7) << 4) |
82                ((A_VAL(&(src_ptr[-4])) >> 7) << 3) |
83                ((A_VAL(&(src_ptr[-5])) >> 7) << 2) |
84                ((A_VAL(&(src_ptr[-6])) >> 7) << 1) |
85                ((A_VAL(&(src_ptr[-7])) >> 7) << 0);
86              src_ptr -= 8;
87              dst_ptr++;
88           }
89      }
90    else
91      {
92         for (x = 0; x < w; x += 8)
93           {
94              *dst_ptr =
95                ((A_VAL(&(src_ptr[ 0])) >> 7) << 0) |
96                ((A_VAL(&(src_ptr[-1])) >> 7) << 1) |
97                ((A_VAL(&(src_ptr[-2])) >> 7) << 2) |
98                ((A_VAL(&(src_ptr[-3])) >> 7) << 3) |
99                ((A_VAL(&(src_ptr[-4])) >> 7) << 4) |
100                ((A_VAL(&(src_ptr[-5])) >> 7) << 5) |
101                ((A_VAL(&(src_ptr[-6])) >> 7) << 6) |
102                ((A_VAL(&(src_ptr[-7])) >> 7) << 7);
103              src_ptr -= 8;
104              dst_ptr++;
105           }
106      }
107    w += 7;
108    for (; x < w; x ++)
109      {
110         XPutPixel(xob->xim, x, y, A_VAL(src_ptr) >> 7);
111         src_ptr--;
112      }
113 }
114
115 void
116 evas_software_xlib_x_write_mask_line_vert(Outbuf *buf, X_Output_Buffer *xob, 
117                                           DATA32 *src, 
118                                           int h, int ym, int w)
119 {
120    int y;
121    DATA32 *src_ptr;
122    DATA8 *dst_ptr;
123    int bpl = 0;
124
125    src_ptr = src;
126    dst_ptr = evas_software_xlib_x_output_buffer_data(xob, &bpl);
127    dst_ptr = dst_ptr + (bpl * ym);
128    h -= 7;
129    if (buf->priv.x11.xlib.bit_swap)
130      {
131         for (y = 0; y < h; y += 8)
132           {
133              *dst_ptr =
134                ((A_VAL(&(src_ptr[0 * w])) >> 7) << 7) |
135                ((A_VAL(&(src_ptr[1 * w])) >> 7) << 6) |
136                ((A_VAL(&(src_ptr[2 * w])) >> 7) << 5) |
137                ((A_VAL(&(src_ptr[3 * w])) >> 7) << 4) |
138                ((A_VAL(&(src_ptr[4 * w])) >> 7) << 3) |
139                ((A_VAL(&(src_ptr[5 * w])) >> 7) << 2) |
140                ((A_VAL(&(src_ptr[6 * w])) >> 7) << 1) |
141                ((A_VAL(&(src_ptr[7 * w])) >> 7) << 0);
142              src_ptr += 8 * w;
143              dst_ptr++;
144           }
145      }
146    else
147      {
148         for (y = 0; y < h; y += 8)
149           {
150              *dst_ptr =
151                ((A_VAL(&(src_ptr[0 * w])) >> 7) << 0) |
152                ((A_VAL(&(src_ptr[1 * w])) >> 7) << 1) |
153                ((A_VAL(&(src_ptr[2 * w])) >> 7) << 2) |
154                ((A_VAL(&(src_ptr[3 * w])) >> 7) << 3) |
155                ((A_VAL(&(src_ptr[4 * w])) >> 7) << 4) |
156                ((A_VAL(&(src_ptr[5 * w])) >> 7) << 5) |
157                ((A_VAL(&(src_ptr[6 * w])) >> 7) << 6) |
158                ((A_VAL(&(src_ptr[7 * w])) >> 7) << 7);
159              src_ptr += 8 * w;
160              dst_ptr++;
161           }
162      }
163    h += 7;
164    for (; y < h; y ++)
165      {
166         XPutPixel(xob->xim, y, ym, A_VAL(src_ptr) >> 7);
167         src_ptr += w;
168      }
169 }
170
171 void
172 evas_software_xlib_x_write_mask_line_vert_rev(Outbuf *buf, X_Output_Buffer *xob, 
173                                               DATA32 *src, 
174                                               int h, int ym, int w)
175 {
176    int y;
177    DATA32 *src_ptr;
178    DATA8 *dst_ptr;
179    int bpl = 0;
180
181    src_ptr = src + ((h - 1) * w);
182    dst_ptr = evas_software_xlib_x_output_buffer_data(xob, &bpl);
183    dst_ptr = dst_ptr + (bpl * ym);
184    h -= 7;
185    if (buf->priv.x11.xlib.bit_swap)
186      {
187         for (y = 0; y < h; y += 8)
188           {
189              *dst_ptr =
190                ((A_VAL(&(src_ptr[ 0 * w])) >> 7) << 7) |
191                ((A_VAL(&(src_ptr[-1 * w])) >> 7) << 6) |
192                ((A_VAL(&(src_ptr[-2 * w])) >> 7) << 5) |
193                ((A_VAL(&(src_ptr[-3 * w])) >> 7) << 4) |
194                ((A_VAL(&(src_ptr[-4 * w])) >> 7) << 3) |
195                ((A_VAL(&(src_ptr[-5 * w])) >> 7) << 2) |
196                ((A_VAL(&(src_ptr[-6 * w])) >> 7) << 1) |
197                ((A_VAL(&(src_ptr[-7 * w])) >> 7) << 0);
198              src_ptr -= 8 * w;
199              dst_ptr++;
200           }
201      }
202    else
203      {
204         for (y = 0; y < h; y += 8)
205           {
206              *dst_ptr =
207                ((A_VAL(&(src_ptr[ 0 * w])) >> 7) << 0) |
208                ((A_VAL(&(src_ptr[-1 * w])) >> 7) << 1) |
209                ((A_VAL(&(src_ptr[-2 * w])) >> 7) << 2) |
210                ((A_VAL(&(src_ptr[-3 * w])) >> 7) << 3) |
211                ((A_VAL(&(src_ptr[-4 * w])) >> 7) << 4) |
212                ((A_VAL(&(src_ptr[-5 * w])) >> 7) << 5) |
213                ((A_VAL(&(src_ptr[-6 * w])) >> 7) << 6) |
214                ((A_VAL(&(src_ptr[-7 * w])) >> 7) << 7);
215              src_ptr -= 8 * w;
216              dst_ptr++;
217           }
218      }
219    h += 7;
220    for (; y < h; y ++)
221      {
222         XPutPixel(xob->xim, y, ym, A_VAL(src_ptr) >> 7);
223         src_ptr -= w;
224      }
225 }
226
227 int
228 evas_software_xlib_x_can_do_shm(Display *d)
229 {
230    static Display *cached_d = NULL;
231    static int cached_result = 0;
232    
233    if (d == cached_d) return cached_result;
234    cached_d = d;
235    if (XShmQueryExtension(d))
236      {
237         X_Output_Buffer *xob;
238
239         xob = evas_software_xlib_x_output_buffer_new
240           (d, DefaultVisual(d, DefaultScreen(d)),
241            DefaultDepth(d, DefaultScreen(d)), 16, 16, 2, NULL);
242         if (!xob)
243           {
244              cached_result = 0;
245              return 0;
246           }
247         evas_software_xlib_x_output_buffer_free(xob, 1);
248         cached_result = 1;
249         return 1;
250      }
251    cached_result = 0;
252    return 0;
253 }
254
255 static void
256 x_output_tmp_x_err(Display *d __UNUSED__, XErrorEvent *ev __UNUSED__)
257 {
258    _x_err = 1;
259    return;
260 }
261
262 //static int creates = 0;
263
264 X_Output_Buffer *
265 evas_software_xlib_x_output_buffer_new(Display *d, Visual *v, int depth, int w, int h, int try_shm, void *data)
266 {
267    X_Output_Buffer *xob;
268
269    xob = calloc(1, sizeof(X_Output_Buffer));
270    if (!xob) return NULL;
271
272    xob->display = d;
273    xob->visual = v;
274    xob->xim = NULL;
275    xob->shm_info = NULL;
276    xob->w = w;
277    xob->h = h;
278
279    if (try_shm > 0)
280      {
281         xob->shm_info = malloc(sizeof(XShmSegmentInfo));
282         if (xob->shm_info)
283           {
284              xob->xim = XShmCreateImage(d, v, depth, ZPixmap, NULL,
285                                         xob->shm_info, w, h);
286              if (xob->xim)
287                {
288                   xob->shm_info->shmid = shmget(IPC_PRIVATE,
289                                                 xob->xim->bytes_per_line *
290                                                 xob->xim->height,
291                                                 IPC_CREAT | 0777);
292                   if (xob->shm_info->shmid >= 0)
293                     {
294                        xob->shm_info->readOnly = False;
295                        xob->shm_info->shmaddr = xob->xim->data =
296                          shmat(xob->shm_info->shmid, 0, 0);
297                        if (xob->shm_info->shmaddr != NULL)
298                          {
299                             XErrorHandler ph;
300                             
301                             if (try_shm == 2) // only needed during testing
302                               {
303                                  XSync(d, False);
304                                  _x_err = 0;
305                                  ph = XSetErrorHandler((XErrorHandler)
306                                                        x_output_tmp_x_err);
307                               }
308 #if defined(EVAS_FRAME_QUEUING) && defined(LIBXEXT_VERSION_LOW)
309                     /* workaround for libXext of lower then 1.1.1 */
310                     if (evas_common_frameq_enabled())
311                        XLockDisplay(d);
312 #endif
313                             XShmAttach(d, xob->shm_info);
314 #if defined(EVAS_FRAME_QUEUING) && defined(LIBXEXT_VERSION_LOW)
315                     /* workaround for libXext of lower then 1.1.1 */
316                     if (evas_common_frameq_enabled())
317                        XUnlockDisplay(d);
318 #endif
319
320                             if (try_shm == 2) // only needed during testing
321                               {
322                                  XSync(d, False); 
323                                  XSetErrorHandler((XErrorHandler)ph);
324                               }
325                             if (!_x_err)
326                               {
327 //                               printf("SHM++ ID=%i -> %i bytes [%i creates]\n",
328 //                                      xob->shm_info->shmid,
329 //                                      xob->xim->bytes_per_line * xob->xim->height,
330 //                                      creates);
331 //                               creates++;
332                                  xob->bpl = xob->xim->bytes_per_line;
333                                  xob->psize = xob->bpl * xob->h;
334                                  return xob;
335                               }
336                          }
337                        shmdt(xob->shm_info->shmaddr);
338                        shmctl(xob->shm_info->shmid, IPC_RMID, 0);
339                     }
340                   if (xob->xim) XDestroyImage(xob->xim);
341                   xob->xim = NULL;
342                }
343              if (xob->shm_info) free(xob->shm_info);
344              xob->shm_info = NULL;
345           }
346      }
347
348    if (try_shm > 1) return NULL;
349
350    xob->xim = XCreateImage(d, v, depth, ZPixmap, 0, data, w, h, 32, 0);
351    if (!xob->xim)
352      {
353         free(xob);
354         return NULL;
355      }
356
357    xob->data = data;
358
359    if (!xob->xim->data)
360      {
361         xob->xim->data = malloc(xob->xim->bytes_per_line * xob->xim->height);
362         if (!xob->xim->data)
363           {
364              XDestroyImage(xob->xim);
365              free(xob);
366              return NULL;
367           }
368      }
369    xob->bpl = xob->xim->bytes_per_line;
370    xob->psize = xob->bpl * xob->h;
371    return xob;
372 }
373
374 void
375 evas_software_xlib_x_output_buffer_free(X_Output_Buffer *xob, int sync)
376 {
377    if (xob->shm_info)
378      {
379 //      printf("SHM-- ID=%i -> %i bytes, [sync=%i]\n",
380 //             xob->shm_info->shmid,
381 //             xob->xim->bytes_per_line * xob->xim->height,
382 //             sync);
383         if (sync) XSync(xob->display, False);
384         XShmDetach(xob->display, xob->shm_info);
385         XDestroyImage(xob->xim);
386         shmdt(xob->shm_info->shmaddr);
387         shmctl(xob->shm_info->shmid, IPC_RMID, 0);
388         free(xob->shm_info);
389      }
390    else
391      {
392         if (xob->data) xob->xim->data = NULL;
393         XDestroyImage(xob->xim);
394      }
395    free(xob);
396 }
397
398 void
399 evas_software_xlib_x_output_buffer_paste(X_Output_Buffer *xob, Drawable d, GC gc, int x, int y, int sync)
400 {
401    if (xob->shm_info)
402      {
403 //      printf("shm\n");
404         XShmPutImage(xob->display, d, gc, xob->xim, 0, 0, x, y,
405                      xob->w, xob->h, False);
406         if (sync) XSync(xob->display, False);
407      }
408    else
409      {
410 //      printf("NO! shm\n");
411         XPutImage(xob->display, d, gc, xob->xim, 0, 0, x, y,
412                   xob->w, xob->h);
413      }
414 }
415
416 DATA8 *
417 evas_software_xlib_x_output_buffer_data(X_Output_Buffer *xob, int *bytes_per_line_ret)
418 {
419    if (bytes_per_line_ret) *bytes_per_line_ret = xob->xim->bytes_per_line;
420    return (DATA8 *)xob->xim->data;
421 }
422
423 int
424 evas_software_xlib_x_output_buffer_depth(X_Output_Buffer *xob)
425 {
426    return xob->xim->bits_per_pixel;
427 }
428
429 int
430 evas_software_xlib_x_output_buffer_byte_order(X_Output_Buffer *xob)
431 {
432    return xob->xim->byte_order;
433 }
434
435 int
436 evas_software_xlib_x_output_buffer_bit_order(X_Output_Buffer *xob)
437 {
438    return xob->xim->bitmap_bit_order;
439 }