move around - flatter.
[profile/ivi/evas.git] / src / modules / engines / software_xcb / evas_xcb_buffer.c
1 #include "evas_common.h"
2 #include "evas_engine.h"
3
4 static int _xcb_err = 0;
5
6 void
7 evas_software_xcb_x_write_mask_line(Outbuf            *buf,
8                                     Xcb_Output_Buffer *xcbob,
9                                     DATA32            *src,
10                                     int                w,
11                                     int                y)
12 {
13    int     x;
14    DATA32 *src_ptr;
15    DATA8  *dst_ptr;
16    int     bpl = 0;
17
18    src_ptr = src;
19    dst_ptr = evas_software_xcb_x_output_buffer_data(xcbob, &bpl);
20    dst_ptr = dst_ptr + (bpl * y);
21    w -= 7;
22    if (buf->priv.x.bit_swap)
23      {
24         for (x = 0; x < w; x += 8)
25           {
26              *dst_ptr =
27                ((A_VAL(&(src_ptr[0])) >> 7) << 7) |
28                ((A_VAL(&(src_ptr[1])) >> 7) << 6) |
29                ((A_VAL(&(src_ptr[2])) >> 7) << 5) |
30                ((A_VAL(&(src_ptr[3])) >> 7) << 4) |
31                ((A_VAL(&(src_ptr[4])) >> 7) << 3) |
32                ((A_VAL(&(src_ptr[5])) >> 7) << 2) |
33                ((A_VAL(&(src_ptr[6])) >> 7) << 1) |
34                ((A_VAL(&(src_ptr[7])) >> 7) << 0);
35              src_ptr += 8;
36              dst_ptr++;
37           }
38      }
39    else
40      {
41         for (x = 0; x < w; x += 8)
42           {
43              *dst_ptr =
44                ((A_VAL(&(src_ptr[0])) >> 7) << 0) |
45                ((A_VAL(&(src_ptr[1])) >> 7) << 1) |
46                ((A_VAL(&(src_ptr[2])) >> 7) << 2) |
47                ((A_VAL(&(src_ptr[3])) >> 7) << 3) |
48                ((A_VAL(&(src_ptr[4])) >> 7) << 4) |
49                ((A_VAL(&(src_ptr[5])) >> 7) << 5) |
50                ((A_VAL(&(src_ptr[6])) >> 7) << 6) |
51                ((A_VAL(&(src_ptr[7])) >> 7) << 7);
52              src_ptr += 8;
53              dst_ptr++;
54           }
55      }
56    w += 7;
57    for (; x < w; x ++)
58       {
59          xcb_image_put_pixel(xcbob->image, x, y, A_VAL(src_ptr) >> 7);
60          src_ptr++;
61       }
62 }
63
64 int
65 evas_software_xcb_x_can_do_shm(xcb_connection_t *c,
66                                xcb_screen_t     *screen)
67 {
68    static xcb_connection_t  *cached_c = NULL;
69    static int                cached_result = 0;
70
71    if (c == cached_c) return cached_result;
72    cached_c = c;
73
74    if (xcb_get_extension_data(c, &xcb_shm_id))
75      {
76         Xcb_Output_Buffer *xcbob;
77
78         xcbob = evas_software_xcb_x_output_buffer_new(c,
79                                                       screen->root_depth,
80                                                       16,
81                                                       16,
82                                                       2,
83                                                       NULL);
84         if (!xcbob)
85           {
86              cached_result = 0;
87              return 0;
88           }
89         evas_software_xcb_x_output_buffer_free(xcbob, 1);
90         cached_result = 1;
91         return 1;
92      }
93    cached_result = 0;
94    return 0;
95 }
96
97 /*
98  * FIXME: no error mechanism
99  */
100
101 /* static void */
102 /* x_output_tmp_xcb_err(xcb_connection_t *c, XErrorEvent * ev) */
103 /* { */
104 /*    _xcb_err = 1; */
105 /*    return; */
106 /* } */
107
108 Xcb_Output_Buffer *
109 evas_software_xcb_x_output_buffer_new(xcb_connection_t *c,
110                                       int               depth,
111                                       int               w,
112                                       int               h,
113                                       int               try_shm,
114                                       void             *data)
115 {
116    Xcb_Output_Buffer *xcbob;
117
118    xcbob = calloc(1, sizeof(Xcb_Output_Buffer));
119    if (!xcbob) return NULL;
120
121    xcbob->connection = c;
122    xcbob->image      = NULL;
123    xcbob->shm_info   = NULL;
124    xcbob->w = w;
125    xcbob->h = h;
126
127    try_shm = 0;
128
129    if (try_shm > 0)
130      {
131         xcbob->shm_info = malloc(sizeof(xcb_shm_segment_info_t));
132         if (xcbob->shm_info)
133           {
134              xcbob->shm_info->shmseg = xcb_generate_id(c);
135              xcbob->image = xcb_image_create_native(c, w, h,
136                                                     XCB_IMAGE_FORMAT_Z_PIXMAP,
137                                                     depth, NULL, ~0, NULL);
138              if (xcbob->image)
139                {
140                   xcbob->shm_info->shmid = shmget(IPC_PRIVATE,
141                                                   xcbob->image->size,
142                                                   IPC_CREAT | 0777);
143                   if (xcbob->shm_info->shmid >= 0)
144                     {
145                        xcbob->shm_info->shmaddr = xcbob->image->data =
146                          shmat(xcbob->shm_info->shmid, 0, 0);
147                        if (xcbob->shm_info->shmaddr != NULL)
148                          {
149                             /*
150                              * FIXME: no error mechanism
151                              */
152
153                            /* XErrorHandler ph; */
154                            /* EventHandlers eh; */
155
156                            //                           free(xcb_get_input_focus_reply(c, xcb_get_input_focus_unchecked(c), NULL));
157                            _xcb_err = 0;
158                            /* ph = XSetErrorHandler((XErrorHandler) */
159                            /* x_output_tmp_x_err); */
160                            xcb_shm_attach(c,
161                                           xcbob->shm_info->shmseg,
162                                           xcbob->shm_info->shmid, 0);
163                            //                           free(xcb_get_input_focus_reply(c, xcb_get_input_focus_unchecked(c), NULL));
164                            /* XSetErrorHandler((XErrorHandler)ph); */
165                            if (!_xcb_err)
166                              {
167                                  xcbob->bpl = xcbob->image->stride;
168                                  xcbob->psize = xcbob->bpl * xcbob->h;
169                                  return xcbob;
170                              }
171                          }
172                        shmdt(xcbob->shm_info->shmaddr);
173                        shmctl(xcbob->shm_info->shmid, IPC_RMID, 0);
174                     }
175                   if (xcbob->image) xcb_image_destroy(xcbob->image);
176                   xcbob->image = NULL;
177                }
178              if (xcbob->shm_info) free(xcbob->shm_info);
179              xcbob->shm_info = NULL;
180           }
181      }
182
183    if (try_shm > 1) return NULL;
184
185    xcbob->image = xcb_image_create_native(c, w, h, XCB_IMAGE_FORMAT_Z_PIXMAP,
186                                           depth, NULL, ~0, NULL);
187    if (!xcbob->image)
188      {
189         free(xcbob);
190         return NULL;
191      }
192
193    xcbob->data = data;
194
195    if (!xcbob->image->data)
196      {
197         xcbob->image->data = malloc(xcbob->image->size);
198         if (!xcbob->image->data)
199           {
200              xcb_image_destroy(xcbob->image);
201              free(xcbob);
202              return NULL;
203           }
204      }
205
206    xcbob->bpl = xcbob->image->stride;
207    xcbob->psize = xcbob->image->size;
208
209    return xcbob;
210 }
211
212 void
213 evas_software_xcb_x_output_buffer_free(Xcb_Output_Buffer *xcbob,
214                                        int                sync)
215 {
216    if (xcbob->shm_info)
217      {
218         if (sync)
219           free(xcb_get_input_focus_reply(xcbob->connection,
220                                          xcb_get_input_focus_unchecked(xcbob->connection),
221                                          NULL));
222         xcb_shm_detach(xcbob->connection, xcbob->shm_info->shmseg);
223         xcb_image_destroy(xcbob->image);
224         shmdt(xcbob->shm_info->shmaddr);
225         shmctl(xcbob->shm_info->shmid, IPC_RMID, 0);
226         free(xcbob->shm_info);
227      }
228    else
229      {
230         if (xcbob->data) xcbob->image->data = NULL;
231         xcb_image_destroy(xcbob->image);
232      }
233    free(xcbob);
234 }
235
236 void
237 evas_software_xcb_x_output_buffer_paste(Xcb_Output_Buffer    *xcbob,
238                                         xcb_drawable_t        d,
239                                         xcb_gcontext_t        gc,
240                                         int                   x,
241                                         int                   y,
242                                         int                   sync)
243 {
244    if (xcbob->shm_info)
245      {
246         xcb_image_shm_put(xcbob->connection, d, gc,
247                           xcbob->image, *xcbob->shm_info,
248                           0, 0,
249                           x, y,
250                           xcbob->image->width, xcbob->image->height,
251                           0);
252         if (sync)
253           free(xcb_get_input_focus_reply(xcbob->connection,
254                                          xcb_get_input_focus_unchecked(xcbob->connection),
255                                          NULL));
256      }
257    else
258       xcb_image_put(xcbob->connection, d, gc,
259                     xcbob->image,
260                     x, y, 0);
261 }
262
263 DATA8 *
264 evas_software_xcb_x_output_buffer_data(Xcb_Output_Buffer *xcbob,
265                                        int               *bytes_per_line_ret)
266 {
267    if (bytes_per_line_ret) *bytes_per_line_ret = xcbob->image->stride;
268    return xcbob->image->data;
269 }
270
271 int
272 evas_software_xcb_x_output_buffer_depth(Xcb_Output_Buffer *xcbob)
273 {
274    return xcbob->image->bpp;
275 }
276
277 int
278 evas_software_xcb_x_output_buffer_byte_order(Xcb_Output_Buffer *xcbob)
279 {
280    return xcbob->image->byte_order;
281 }
282
283 int
284 evas_software_xcb_x_output_buffer_bit_order(Xcb_Output_Buffer *xcbob)
285 {
286    return xcbob->image->bit_order;
287 }