b091d14610408200b719126c16e42d8827935070
[framework/uifw/evas.git] / src / modules / engines / software_x11 / evas_xcb_buffer.c
1 #include "evas_common.h"
2
3 #include "evas_xcb_buffer.h"
4
5 static int _xcb_err = 0;
6
7 void
8 evas_software_xcb_x_write_mask_line(Outbuf            *buf,
9                                     Xcb_Output_Buffer *xcbob,
10                                     DATA32            *src,
11                                     int                w,
12                                     int                y)
13 {
14    int     x;
15    DATA32 *src_ptr;
16    DATA8  *dst_ptr;
17    int     bpl = 0;
18
19    src_ptr = src;
20    dst_ptr = evas_software_xcb_x_output_buffer_data(xcbob, &bpl);
21    dst_ptr = dst_ptr + (bpl * y);
22    w -= 7;
23    if (buf->priv.x11.xcb.bit_swap)
24      {
25         for (x = 0; x < w; x += 8)
26           {
27              *dst_ptr =
28                ((A_VAL(&(src_ptr[0])) >> 7) << 7) |
29                ((A_VAL(&(src_ptr[1])) >> 7) << 6) |
30                ((A_VAL(&(src_ptr[2])) >> 7) << 5) |
31                ((A_VAL(&(src_ptr[3])) >> 7) << 4) |
32                ((A_VAL(&(src_ptr[4])) >> 7) << 3) |
33                ((A_VAL(&(src_ptr[5])) >> 7) << 2) |
34                ((A_VAL(&(src_ptr[6])) >> 7) << 1) |
35                ((A_VAL(&(src_ptr[7])) >> 7) << 0);
36              src_ptr += 8;
37              dst_ptr++;
38           }
39      }
40    else
41      {
42         for (x = 0; x < w; x += 8)
43           {
44              *dst_ptr =
45                ((A_VAL(&(src_ptr[0])) >> 7) << 0) |
46                ((A_VAL(&(src_ptr[1])) >> 7) << 1) |
47                ((A_VAL(&(src_ptr[2])) >> 7) << 2) |
48                ((A_VAL(&(src_ptr[3])) >> 7) << 3) |
49                ((A_VAL(&(src_ptr[4])) >> 7) << 4) |
50                ((A_VAL(&(src_ptr[5])) >> 7) << 5) |
51                ((A_VAL(&(src_ptr[6])) >> 7) << 6) |
52                ((A_VAL(&(src_ptr[7])) >> 7) << 7);
53              src_ptr += 8;
54              dst_ptr++;
55           }
56      }
57    w += 7;
58    for (; x < w; x ++)
59       {
60          xcb_image_put_pixel(xcbob->image, x, y, A_VAL(src_ptr) >> 7);
61          src_ptr++;
62       }
63 }
64
65 void
66 evas_software_xcb_x_write_mask_line_rev(Outbuf            *buf,
67                                         Xcb_Output_Buffer *xcbob,
68                                         DATA32            *src,
69                                         int                w,
70                                         int                y)
71 {
72    int     x;
73    DATA32 *src_ptr;
74    DATA8  *dst_ptr;
75    int     bpl = 0;
76
77    src_ptr = src + w - 1;
78    dst_ptr = evas_software_xcb_x_output_buffer_data(xcbob, &bpl);
79    dst_ptr = dst_ptr + (bpl * y);
80    w -= 7;
81    if (buf->priv.x11.xcb.bit_swap)
82      {
83         for (x = 0; x < w; x += 8)
84           {
85              *dst_ptr =
86                ((A_VAL(&(src_ptr[ 0])) >> 7) << 7) |
87                ((A_VAL(&(src_ptr[-1])) >> 7) << 6) |
88                ((A_VAL(&(src_ptr[-2])) >> 7) << 5) |
89                ((A_VAL(&(src_ptr[-3])) >> 7) << 4) |
90                ((A_VAL(&(src_ptr[-4])) >> 7) << 3) |
91                ((A_VAL(&(src_ptr[-5])) >> 7) << 2) |
92                ((A_VAL(&(src_ptr[-6])) >> 7) << 1) |
93                ((A_VAL(&(src_ptr[-7])) >> 7) << 0);
94              src_ptr -= 8;
95              dst_ptr++;
96           }
97      }
98    else
99      {
100         for (x = 0; x < w; x += 8)
101           {
102              *dst_ptr =
103                ((A_VAL(&(src_ptr[ 0])) >> 7) << 0) |
104                ((A_VAL(&(src_ptr[-1])) >> 7) << 1) |
105                ((A_VAL(&(src_ptr[-2])) >> 7) << 2) |
106                ((A_VAL(&(src_ptr[-3])) >> 7) << 3) |
107                ((A_VAL(&(src_ptr[-4])) >> 7) << 4) |
108                ((A_VAL(&(src_ptr[-5])) >> 7) << 5) |
109                ((A_VAL(&(src_ptr[-6])) >> 7) << 6) |
110                ((A_VAL(&(src_ptr[-7])) >> 7) << 7);
111              src_ptr -= 8;
112              dst_ptr++;
113           }
114      }
115    w += 7;
116    for (; x < w; x ++)
117      {
118         xcb_image_put_pixel(xcbob->image, x, y, A_VAL(src_ptr) >> 7);
119         src_ptr--;
120      }
121 }
122
123 void
124 evas_software_xcb_x_write_mask_line_vert(Outbuf            *buf,
125                                          Xcb_Output_Buffer *xcbob,
126                                          DATA32            *src,
127                                          int                h,
128                                          int                ym,
129                                          int                w)
130 {
131    int     y;
132    DATA32 *src_ptr;
133    DATA8  *dst_ptr;
134    int     bpl = 0;
135
136    src_ptr = src;
137    dst_ptr = evas_software_xcb_x_output_buffer_data(xcbob, &bpl);
138    dst_ptr = dst_ptr + (bpl * ym);
139    h -= 7;
140    if (buf->priv.x11.xcb.bit_swap)
141      {
142         for (y = 0; y < h; y += 8)
143           {
144              *dst_ptr =
145                ((A_VAL(&(src_ptr[0 * w])) >> 7) << 7) |
146                ((A_VAL(&(src_ptr[1 * w])) >> 7) << 6) |
147                ((A_VAL(&(src_ptr[2 * w])) >> 7) << 5) |
148                ((A_VAL(&(src_ptr[3 * w])) >> 7) << 4) |
149                ((A_VAL(&(src_ptr[4 * w])) >> 7) << 3) |
150                ((A_VAL(&(src_ptr[5 * w])) >> 7) << 2) |
151                ((A_VAL(&(src_ptr[6 * w])) >> 7) << 1) |
152                ((A_VAL(&(src_ptr[7 * w])) >> 7) << 0);
153              src_ptr += 8 * w;
154              dst_ptr++;
155           }
156      }
157    else
158      {
159         for (y = 0; y < h; y += 8)
160           {
161              *dst_ptr =
162                ((A_VAL(&(src_ptr[0 * w])) >> 7) << 0) |
163                ((A_VAL(&(src_ptr[1 * w])) >> 7) << 1) |
164                ((A_VAL(&(src_ptr[2 * w])) >> 7) << 2) |
165                ((A_VAL(&(src_ptr[3 * w])) >> 7) << 3) |
166                ((A_VAL(&(src_ptr[4 * w])) >> 7) << 4) |
167                ((A_VAL(&(src_ptr[5 * w])) >> 7) << 5) |
168                ((A_VAL(&(src_ptr[6 * w])) >> 7) << 6) |
169                ((A_VAL(&(src_ptr[7 * w])) >> 7) << 7);
170              src_ptr += 8 * w;
171              dst_ptr++;
172           }
173      }
174    h += 7;
175    for (; y < h; y ++)
176      {
177         xcb_image_put_pixel(xcbob->image, y, ym, A_VAL(src_ptr) >> 7);
178         src_ptr += w;
179      }
180 }
181
182 void
183 evas_software_xcb_x_write_mask_line_vert_rev(Outbuf            *buf,
184                                              Xcb_Output_Buffer *xcbob,
185                                              DATA32            *src,
186                                              int                h,
187                                              int                ym,
188                                              int                w)
189 {
190    int     y;
191    DATA32 *src_ptr;
192    DATA8  *dst_ptr;
193    int     bpl = 0;
194
195    src_ptr = src + ((h - 1) * w);
196    dst_ptr = evas_software_xcb_x_output_buffer_data(xcbob, &bpl);
197    dst_ptr = dst_ptr + (bpl * ym);
198    h -= 7;
199    if (buf->priv.x11.xcb.bit_swap)
200      {
201         for (y = 0; y < h; y += 8)
202           {
203              *dst_ptr =
204                ((A_VAL(&(src_ptr[ 0 * w])) >> 7) << 7) |
205                ((A_VAL(&(src_ptr[-1 * w])) >> 7) << 6) |
206                ((A_VAL(&(src_ptr[-2 * w])) >> 7) << 5) |
207                ((A_VAL(&(src_ptr[-3 * w])) >> 7) << 4) |
208                ((A_VAL(&(src_ptr[-4 * w])) >> 7) << 3) |
209                ((A_VAL(&(src_ptr[-5 * w])) >> 7) << 2) |
210                ((A_VAL(&(src_ptr[-6 * w])) >> 7) << 1) |
211                ((A_VAL(&(src_ptr[-7 * w])) >> 7) << 0);
212              src_ptr -= 8 * w;
213              dst_ptr++;
214           }
215      }
216    else
217      {
218         for (y = 0; y < h; y += 8)
219           {
220              *dst_ptr =
221                ((A_VAL(&(src_ptr[ 0 * w])) >> 7) << 0) |
222                ((A_VAL(&(src_ptr[-1 * w])) >> 7) << 1) |
223                ((A_VAL(&(src_ptr[-2 * w])) >> 7) << 2) |
224                ((A_VAL(&(src_ptr[-3 * w])) >> 7) << 3) |
225                ((A_VAL(&(src_ptr[-4 * w])) >> 7) << 4) |
226                ((A_VAL(&(src_ptr[-5 * w])) >> 7) << 5) |
227                ((A_VAL(&(src_ptr[-6 * w])) >> 7) << 6) |
228                ((A_VAL(&(src_ptr[-7 * w])) >> 7) << 7);
229              src_ptr -= 8 * w;
230              dst_ptr++;
231           }
232      }
233    h += 7;
234    for (; y < h; y ++)
235      {
236         xcb_image_put_pixel(xcbob->image, y, ym, A_VAL(src_ptr) >> 7);
237         src_ptr -= w;
238      }
239 }
240
241 int
242 evas_software_xcb_x_can_do_shm(xcb_connection_t *c,
243                                xcb_screen_t     *screen)
244 {
245    static xcb_connection_t  *cached_c = NULL;
246    static int                cached_result = 0;
247
248    if (c == cached_c) return cached_result;
249    cached_c = c;
250
251    if (xcb_get_extension_data(c, &xcb_shm_id))
252      {
253         Xcb_Output_Buffer *xcbob;
254
255         xcbob = evas_software_xcb_x_output_buffer_new(c,
256                                                       screen->root_depth,
257                                                       16,
258                                                       16,
259                                                       2,
260                                                       NULL);
261         if (!xcbob)
262           {
263              cached_result = 0;
264              return 0;
265           }
266         evas_software_xcb_x_output_buffer_free(xcbob, 1);
267         cached_result = 1;
268         return 1;
269      }
270    cached_result = 0;
271    return 0;
272 }
273
274 /*
275  * FIXME: no error mechanism
276  */
277
278 /* static void */
279 /* x_output_tmp_xcb_err(xcb_connection_t *c, XErrorEvent * ev) */
280 /* { */
281 /*    _xcb_err = 1; */
282 /*    return; */
283 /* } */
284
285 Xcb_Output_Buffer *
286 evas_software_xcb_x_output_buffer_new(xcb_connection_t *c,
287                                       int               depth,
288                                       int               w,
289                                       int               h,
290                                       int               try_shm,
291                                       void             *data)
292 {
293    Xcb_Output_Buffer *xcbob;
294
295    xcbob = calloc(1, sizeof(Xcb_Output_Buffer));
296    if (!xcbob) return NULL;
297
298    xcbob->connection = c;
299    xcbob->image      = NULL;
300    xcbob->shm_info   = NULL;
301    xcbob->w = w;
302    xcbob->h = h;
303
304    if (try_shm > 0)
305      {
306         xcbob->shm_info = malloc(sizeof(xcb_shm_segment_info_t));
307         if (xcbob->shm_info)
308           {
309              xcbob->shm_info->shmseg = xcb_generate_id(c);
310              xcbob->image = xcb_image_create_native(c, w, h,
311                                                     XCB_IMAGE_FORMAT_Z_PIXMAP,
312                                                     depth, NULL, ~0, NULL);
313              if (xcbob->image)
314                {
315                   xcbob->shm_info->shmid = shmget(IPC_PRIVATE,
316                                                   xcbob->image->size,
317                                                   IPC_CREAT | 0777);
318                   if (xcbob->shm_info->shmid >= 0)
319                     {
320                        xcbob->shm_info->shmaddr = xcbob->image->data =
321                          shmat(xcbob->shm_info->shmid, 0, 0);
322                        if (xcbob->shm_info->shmaddr != NULL)
323                          {
324                             /*
325                              * FIXME: no error mechanism
326                              */
327
328                            /* XErrorHandler ph; */
329                            /* EventHandlers eh; */
330
331                            free(xcb_get_input_focus_reply(c, xcb_get_input_focus_unchecked(c), NULL));
332                            _xcb_err = 0;
333                            /* ph = XSetErrorHandler((XErrorHandler) */
334                            /* x_output_tmp_x_err); */
335                            xcb_shm_attach(c,
336                                           xcbob->shm_info->shmseg,
337                                           xcbob->shm_info->shmid, 0);
338                            free(xcb_get_input_focus_reply(c, xcb_get_input_focus_unchecked(c), NULL));
339                            /* XSetErrorHandler((XErrorHandler)ph); */
340                            if (!_xcb_err)
341                              {
342                                  xcbob->bpl = xcbob->image->stride;
343                                  xcbob->psize = xcbob->bpl * xcbob->h;
344                                  return xcbob;
345                              }
346                          }
347                        shmdt(xcbob->shm_info->shmaddr);
348                        shmctl(xcbob->shm_info->shmid, IPC_RMID, 0);
349                     }
350                   if (xcbob->image) xcb_image_destroy(xcbob->image);
351                   xcbob->image = NULL;
352                }
353              if (xcbob->shm_info) free(xcbob->shm_info);
354              xcbob->shm_info = NULL;
355           }
356      }
357
358    if (try_shm > 1) return NULL;
359
360    xcbob->image = xcb_image_create_native(c, w, h, XCB_IMAGE_FORMAT_Z_PIXMAP,
361                                           depth, NULL, ~0, NULL);
362    if (!xcbob->image)
363      {
364         free(xcbob);
365         return NULL;
366      }
367
368    xcbob->data = data;
369
370    if (!xcbob->image->data)
371      {
372         xcbob->image->data = malloc(xcbob->image->size);
373         if (!xcbob->image->data)
374           {
375              xcb_image_destroy(xcbob->image);
376              free(xcbob);
377              return NULL;
378           }
379      }
380
381    xcbob->bpl = xcbob->image->stride;
382    xcbob->psize = xcbob->image->size;
383
384    return xcbob;
385 }
386
387 void
388 evas_software_xcb_x_output_buffer_free(Xcb_Output_Buffer *xcbob,
389                                        int                sync)
390 {
391    if (xcbob->shm_info)
392      {
393         if (sync)
394           free(xcb_get_input_focus_reply(xcbob->connection,
395                                          xcb_get_input_focus_unchecked(xcbob->connection),
396                                          NULL));
397         xcb_shm_detach(xcbob->connection, xcbob->shm_info->shmseg);
398         free(xcbob->image->data);
399         xcb_image_destroy(xcbob->image);
400         shmdt(xcbob->shm_info->shmaddr);
401         shmctl(xcbob->shm_info->shmid, IPC_RMID, 0);
402         free(xcbob->shm_info);
403      }
404    else
405      {
406         if (xcbob->data) xcbob->image->data = NULL;
407         free(xcbob->image->data);
408         xcb_image_destroy(xcbob->image);
409      }
410    free(xcbob);
411 }
412
413 void
414 evas_software_xcb_x_output_buffer_paste(Xcb_Output_Buffer    *xcbob,
415                                         xcb_drawable_t        d,
416                                         xcb_gcontext_t        gc,
417                                         int                   x,
418                                         int                   y,
419                                         int                   sync)
420 {
421    if (xcbob->shm_info)
422      {
423         xcb_image_shm_put(xcbob->connection, d, gc,
424                           xcbob->image, *xcbob->shm_info,
425                           0, 0,
426                           x, y,
427                           xcbob->image->width, xcbob->image->height,
428                           0);
429         if (sync)
430           free(xcb_get_input_focus_reply(xcbob->connection,
431                                          xcb_get_input_focus_unchecked(xcbob->connection),
432                                          NULL));
433      }
434    else
435       xcb_image_put(xcbob->connection, d, gc,
436                     xcbob->image,
437                     x, y, 0);
438 }
439
440 DATA8 *
441 evas_software_xcb_x_output_buffer_data(Xcb_Output_Buffer *xcbob,
442                                        int               *bytes_per_line_ret)
443 {
444    if (bytes_per_line_ret) *bytes_per_line_ret = xcbob->image->stride;
445    return xcbob->image->data;
446 }
447
448 int
449 evas_software_xcb_x_output_buffer_depth(Xcb_Output_Buffer *xcbob)
450 {
451    return xcbob->image->bpp;
452 }
453
454 int
455 evas_software_xcb_x_output_buffer_byte_order(Xcb_Output_Buffer *xcbob)
456 {
457    return xcbob->image->byte_order;
458 }
459
460 int
461 evas_software_xcb_x_output_buffer_bit_order(Xcb_Output_Buffer *xcbob)
462 {
463    return xcbob->image->bit_order;
464 }