aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/evas/src/modules/engines/software_x11/evas_xcb_buffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/evas/src/modules/engines/software_x11/evas_xcb_buffer.c')
-rw-r--r--libraries/evas/src/modules/engines/software_x11/evas_xcb_buffer.c498
1 files changed, 498 insertions, 0 deletions
diff --git a/libraries/evas/src/modules/engines/software_x11/evas_xcb_buffer.c b/libraries/evas/src/modules/engines/software_x11/evas_xcb_buffer.c
new file mode 100644
index 0000000..49ce721
--- /dev/null
+++ b/libraries/evas/src/modules/engines/software_x11/evas_xcb_buffer.c
@@ -0,0 +1,498 @@
1#include "evas_common.h"
2#include "evas_xcb_buffer.h"
3
4/* local function prototypes */
5static void _xcbob_sync(xcb_connection_t *conn);
6static xcb_image_t *_xcbob_create_native(xcb_connection_t *conn, int w, int h, xcb_image_format_t format, uint8_t depth, void *base, uint32_t bytes, uint8_t *data);
7static xcb_format_t *_xcbob_find_format(const xcb_setup_t *setup, uint8_t depth);
8static xcb_visualtype_t *_xcbob_find_visual_by_id(xcb_screen_t *screen, xcb_visualid_t id);
9
10void
11evas_software_xcb_write_mask_line(Outbuf *buf, Xcb_Output_Buffer *xcbob, DATA32 *src, int w, int y)
12{
13 int x, bpl = 0;
14 DATA32 *src_ptr;
15 DATA8 *dst_ptr;
16
17 src_ptr = src;
18 dst_ptr = evas_software_xcb_output_buffer_data(xcbob, &bpl);
19 dst_ptr = dst_ptr + (bpl * y);
20 w -= 7;
21 if (buf->priv.x11.xcb.bit_swap)
22 {
23 for (x = 0; x < w; x += 8)
24 {
25 *dst_ptr =
26 ((A_VAL(&(src_ptr[0])) >> 7) << 7) |
27 ((A_VAL(&(src_ptr[1])) >> 7) << 6) |
28 ((A_VAL(&(src_ptr[2])) >> 7) << 5) |
29 ((A_VAL(&(src_ptr[3])) >> 7) << 4) |
30 ((A_VAL(&(src_ptr[4])) >> 7) << 3) |
31 ((A_VAL(&(src_ptr[5])) >> 7) << 2) |
32 ((A_VAL(&(src_ptr[6])) >> 7) << 1) |
33 ((A_VAL(&(src_ptr[7])) >> 7) << 0);
34 src_ptr += 8;
35 dst_ptr++;
36 }
37 }
38 else
39 {
40 for (x = 0; x < w; x += 8)
41 {
42 *dst_ptr =
43 ((A_VAL(&(src_ptr[0])) >> 7) << 0) |
44 ((A_VAL(&(src_ptr[1])) >> 7) << 1) |
45 ((A_VAL(&(src_ptr[2])) >> 7) << 2) |
46 ((A_VAL(&(src_ptr[3])) >> 7) << 3) |
47 ((A_VAL(&(src_ptr[4])) >> 7) << 4) |
48 ((A_VAL(&(src_ptr[5])) >> 7) << 5) |
49 ((A_VAL(&(src_ptr[6])) >> 7) << 6) |
50 ((A_VAL(&(src_ptr[7])) >> 7) << 7);
51 src_ptr += 8;
52 dst_ptr++;
53 }
54 }
55 w += 7;
56 for (; x < w; x ++)
57 {
58 xcb_image_put_pixel(xcbob->xim, x, y, A_VAL(src_ptr) >> 7);
59 src_ptr++;
60 }
61}
62
63void
64evas_software_xcb_write_mask_line_rev(Outbuf *buf, Xcb_Output_Buffer *xcbob, DATA32 *src, int w, int y)
65{
66 int x, bpl = 0;
67 DATA32 *src_ptr;
68 DATA8 *dst_ptr;
69
70 src_ptr = src + w - 1;
71 dst_ptr = evas_software_xcb_output_buffer_data(xcbob, &bpl);
72 dst_ptr = dst_ptr + (bpl * y);
73 w -= 7;
74 if (buf->priv.x11.xcb.bit_swap)
75 {
76 for (x = 0; x < w; x += 8)
77 {
78 *dst_ptr =
79 ((A_VAL(&(src_ptr[ 0])) >> 7) << 7) |
80 ((A_VAL(&(src_ptr[-1])) >> 7) << 6) |
81 ((A_VAL(&(src_ptr[-2])) >> 7) << 5) |
82 ((A_VAL(&(src_ptr[-3])) >> 7) << 4) |
83 ((A_VAL(&(src_ptr[-4])) >> 7) << 3) |
84 ((A_VAL(&(src_ptr[-5])) >> 7) << 2) |
85 ((A_VAL(&(src_ptr[-6])) >> 7) << 1) |
86 ((A_VAL(&(src_ptr[-7])) >> 7) << 0);
87 src_ptr -= 8;
88 dst_ptr++;
89 }
90 }
91 else
92 {
93 for (x = 0; x < w; x += 8)
94 {
95 *dst_ptr =
96 ((A_VAL(&(src_ptr[ 0])) >> 7) << 0) |
97 ((A_VAL(&(src_ptr[-1])) >> 7) << 1) |
98 ((A_VAL(&(src_ptr[-2])) >> 7) << 2) |
99 ((A_VAL(&(src_ptr[-3])) >> 7) << 3) |
100 ((A_VAL(&(src_ptr[-4])) >> 7) << 4) |
101 ((A_VAL(&(src_ptr[-5])) >> 7) << 5) |
102 ((A_VAL(&(src_ptr[-6])) >> 7) << 6) |
103 ((A_VAL(&(src_ptr[-7])) >> 7) << 7);
104 src_ptr -= 8;
105 dst_ptr++;
106 }
107 }
108 w += 7;
109 for (; x < w; x ++)
110 {
111 xcb_image_put_pixel(xcbob->xim, x, y, A_VAL(src_ptr) >> 7);
112 src_ptr--;
113 }
114}
115
116void
117evas_software_xcb_write_mask_line_vert(Outbuf *buf, Xcb_Output_Buffer *xcbob, DATA32 *src, int h, int y, int w)
118{
119 int yy, bpl = 0;
120 DATA32 *src_ptr;
121 DATA8 *dst_ptr;
122
123 src_ptr = src;
124 dst_ptr = evas_software_xcb_output_buffer_data(xcbob, &bpl);
125 dst_ptr = dst_ptr + (bpl * y);
126 h -= 7;
127 if (buf->priv.x11.xcb.bit_swap)
128 {
129 for (yy = 0; yy < h; yy += 8)
130 {
131 *dst_ptr =
132 ((A_VAL(&(src_ptr[0 * w])) >> 7) << 7) |
133 ((A_VAL(&(src_ptr[1 * w])) >> 7) << 6) |
134 ((A_VAL(&(src_ptr[2 * w])) >> 7) << 5) |
135 ((A_VAL(&(src_ptr[3 * w])) >> 7) << 4) |
136 ((A_VAL(&(src_ptr[4 * w])) >> 7) << 3) |
137 ((A_VAL(&(src_ptr[5 * w])) >> 7) << 2) |
138 ((A_VAL(&(src_ptr[6 * w])) >> 7) << 1) |
139 ((A_VAL(&(src_ptr[7 * w])) >> 7) << 0);
140 src_ptr += 8 * w;
141 dst_ptr++;
142 }
143 }
144 else
145 {
146 for (yy = 0; yy < h; yy += 8)
147 {
148 *dst_ptr =
149 ((A_VAL(&(src_ptr[0 * w])) >> 7) << 0) |
150 ((A_VAL(&(src_ptr[1 * w])) >> 7) << 1) |
151 ((A_VAL(&(src_ptr[2 * w])) >> 7) << 2) |
152 ((A_VAL(&(src_ptr[3 * w])) >> 7) << 3) |
153 ((A_VAL(&(src_ptr[4 * w])) >> 7) << 4) |
154 ((A_VAL(&(src_ptr[5 * w])) >> 7) << 5) |
155 ((A_VAL(&(src_ptr[6 * w])) >> 7) << 6) |
156 ((A_VAL(&(src_ptr[7 * w])) >> 7) << 7);
157 src_ptr += 8 * w;
158 dst_ptr++;
159 }
160 }
161 h += 7;
162 for (; yy < h; yy ++)
163 {
164 xcb_image_put_pixel(xcbob->xim, yy, y, A_VAL(src_ptr) >> 7);
165 src_ptr += w;
166 }
167}
168
169void
170evas_software_xcb_write_mask_line_vert_rev(Outbuf *buf, Xcb_Output_Buffer *xcbob, DATA32 *src, int h, int y, int w)
171{
172 int yy, bpl = 0;
173 DATA32 *src_ptr;
174 DATA8 *dst_ptr;
175
176 src_ptr = src + ((h - 1) * w);
177 dst_ptr = evas_software_xcb_output_buffer_data(xcbob, &bpl);
178 dst_ptr = dst_ptr + (bpl * y);
179 h -= 7;
180 if (buf->priv.x11.xcb.bit_swap)
181 {
182 for (yy = 0; yy < h; yy += 8)
183 {
184 *dst_ptr =
185 ((A_VAL(&(src_ptr[ 0 * w])) >> 7) << 7) |
186 ((A_VAL(&(src_ptr[-1 * w])) >> 7) << 6) |
187 ((A_VAL(&(src_ptr[-2 * w])) >> 7) << 5) |
188 ((A_VAL(&(src_ptr[-3 * w])) >> 7) << 4) |
189 ((A_VAL(&(src_ptr[-4 * w])) >> 7) << 3) |
190 ((A_VAL(&(src_ptr[-5 * w])) >> 7) << 2) |
191 ((A_VAL(&(src_ptr[-6 * w])) >> 7) << 1) |
192 ((A_VAL(&(src_ptr[-7 * w])) >> 7) << 0);
193 src_ptr -= 8 * w;
194 dst_ptr++;
195 }
196 }
197 else
198 {
199 for (yy = 0; yy < h; yy += 8)
200 {
201 *dst_ptr =
202 ((A_VAL(&(src_ptr[ 0 * w])) >> 7) << 0) |
203 ((A_VAL(&(src_ptr[-1 * w])) >> 7) << 1) |
204 ((A_VAL(&(src_ptr[-2 * w])) >> 7) << 2) |
205 ((A_VAL(&(src_ptr[-3 * w])) >> 7) << 3) |
206 ((A_VAL(&(src_ptr[-4 * w])) >> 7) << 4) |
207 ((A_VAL(&(src_ptr[-5 * w])) >> 7) << 5) |
208 ((A_VAL(&(src_ptr[-6 * w])) >> 7) << 6) |
209 ((A_VAL(&(src_ptr[-7 * w])) >> 7) << 7);
210 src_ptr -= 8 * w;
211 dst_ptr++;
212 }
213 }
214 h += 7;
215 for (; yy < h; yy ++)
216 {
217 xcb_image_put_pixel(xcbob->xim, yy, y, A_VAL(src_ptr) >> 7);
218 src_ptr -= w;
219 }
220}
221
222Eina_Bool
223evas_software_xcb_can_do_shm(xcb_connection_t *conn, xcb_screen_t *screen)
224{
225 const xcb_query_extension_reply_t *reply;
226 static xcb_connection_t *cached_conn = NULL;
227 static int cached_result = 0;
228
229 if (conn == cached_conn) return cached_result;
230 cached_conn = conn;
231
232 reply = xcb_get_extension_data(conn, &xcb_shm_id);
233 if ((reply) && (reply->present))
234 {
235 xcb_visualtype_t *visual;
236 Xcb_Output_Buffer *xcbob = NULL;
237
238 visual = _xcbob_find_visual_by_id(screen, screen->root_visual);
239 xcbob =
240 evas_software_xcb_output_buffer_new(conn, visual, screen->root_depth,
241 16, 16, 2, NULL);
242 if (!xcbob)
243 cached_result = 0;
244 else
245 {
246 evas_software_xcb_output_buffer_free(xcbob, EINA_TRUE);
247 cached_result = 1;
248 }
249 }
250 else
251 cached_result = 0;
252
253 return cached_result;
254}
255
256Xcb_Output_Buffer *
257evas_software_xcb_output_buffer_new(xcb_connection_t *conn, xcb_visualtype_t *vis, int depth, int w, int h, int try_shm, unsigned char *data)
258{
259 Xcb_Output_Buffer *xcbob = NULL;
260
261 if (!(xcbob = calloc(1, sizeof(Xcb_Output_Buffer))))
262 return NULL;
263
264 xcbob->connection = conn;
265 xcbob->visual = vis;
266 xcbob->xim = NULL;
267 xcbob->shm_info = NULL;
268 xcbob->w = w;
269 xcbob->h = h;
270
271 if (try_shm > 0)
272 {
273 xcbob->shm_info = malloc(sizeof(xcb_shm_segment_info_t));
274 if (xcbob->shm_info)
275 {
276 xcbob->shm_info->shmseg = xcb_generate_id(conn);
277 xcbob->xim =
278 _xcbob_create_native(conn, w, h, XCB_IMAGE_FORMAT_Z_PIXMAP,
279 depth, NULL, ~0, NULL);
280 if (xcbob->xim)
281 {
282 xcbob->shm_info->shmid =
283 shmget(IPC_PRIVATE,
284 xcbob->xim->stride * xcbob->xim->height,
285 (IPC_CREAT | 0777));
286 if (xcbob->shm_info->shmid == (uint32_t)-1)
287 {
288 xcb_image_destroy(xcbob->xim);
289 free(xcbob->shm_info);
290 free(xcbob);
291 return NULL;
292 }
293 xcbob->shm_info->shmaddr = xcbob->xim->data =
294 shmat(xcbob->shm_info->shmid, 0, 0);
295 if (xcbob->shm_info->shmaddr != ((void *)-1))
296 {
297 /* Sync only needed for testing */
298 if (try_shm == 2) _xcbob_sync(conn);
299
300#if defined(EVAS_FRAME_QUEUING) && defined(LIBXEXT_VERSION_LOW)
301 if (evas_common_frameq_enabled())
302 xcb_grab_server(conn);
303#endif
304 xcb_shm_attach(conn, xcbob->shm_info->shmseg,
305 xcbob->shm_info->shmid, 0);
306#if defined(EVAS_FRAME_QUEUING) && defined(LIBXEXT_VERSION_LOW)
307 if (evas_common_frameq_enabled())
308 xcb_ungrab_server(conn);
309#endif
310 if (try_shm == 2) _xcbob_sync(conn);
311
312 xcbob->bpl = xcbob->xim->stride;
313 xcbob->psize = (xcbob->bpl * xcbob->h);
314 return xcbob;
315 }
316 shmdt(xcbob->shm_info->shmaddr);
317 shmctl(xcbob->shm_info->shmid, IPC_RMID, 0);
318 }
319 if (xcbob->xim) xcb_image_destroy(xcbob->xim);
320 xcbob->xim = NULL;
321 }
322 if (xcbob->shm_info) free(xcbob->shm_info);
323 xcbob->shm_info = NULL;
324 }
325
326 if (try_shm > 1) return NULL;
327
328 /* no shm */
329 xcbob->xim =
330 _xcbob_create_native(conn, w, h, XCB_IMAGE_FORMAT_Z_PIXMAP,
331 depth, NULL, ~0, NULL);
332 if (!xcbob->xim)
333 {
334 free(xcbob);
335 return NULL;
336 }
337
338 xcbob->data = data;
339
340 if (!xcbob->xim->data)
341 {
342 xcbob->xim->data = malloc(xcbob->xim->stride * xcbob->xim->height);
343 if (!xcbob->xim->data)
344 {
345 xcb_image_destroy(xcbob->xim);
346 free(xcbob);
347 return NULL;
348 }
349 }
350 xcbob->bpl = xcbob->xim->stride;
351 xcbob->psize = (xcbob->bpl * xcbob->h);
352 return xcbob;
353}
354
355void
356evas_software_xcb_output_buffer_free(Xcb_Output_Buffer *xcbob, Eina_Bool sync)
357{
358 if (xcbob->shm_info)
359 {
360 if (sync) _xcbob_sync(xcbob->connection);
361 xcb_shm_detach(xcbob->connection, xcbob->shm_info->shmseg);
362 xcb_image_destroy(xcbob->xim);
363 shmdt(xcbob->shm_info->shmaddr);
364 shmctl(xcbob->shm_info->shmid, IPC_RMID, 0);
365 free(xcbob->shm_info);
366 }
367 else
368 {
369 if (xcbob->data) xcbob->xim->data = NULL;
370// free(xcbob->xim->data);
371 xcb_image_destroy(xcbob->xim);
372 }
373 free(xcbob);
374}
375
376void
377evas_software_xcb_output_buffer_paste(Xcb_Output_Buffer *xcbob, xcb_drawable_t drawable, xcb_gcontext_t gc, int x, int y, Eina_Bool sync)
378{
379 if (xcbob->shm_info)
380 {
381 xcb_image_shm_put(xcbob->connection, drawable, gc, xcbob->xim,
382 *xcbob->shm_info, 0, 0, x, y, xcbob->w, xcbob->h, 0);
383 if (sync) _xcbob_sync(xcbob->connection);
384 }
385 else
386 xcb_image_put(xcbob->connection, drawable, gc, xcbob->xim, x, y, 0);
387}
388
389DATA8 *
390evas_software_xcb_output_buffer_data(Xcb_Output_Buffer *xcbob, int *bpl_ret)
391{
392 if (bpl_ret) *bpl_ret = xcbob->xim->stride;
393 return (DATA8 *)xcbob->xim->data;
394}
395
396int
397evas_software_xcb_output_buffer_depth(Xcb_Output_Buffer *xcbob)
398{
399 return xcbob->xim->bpp;
400}
401
402int
403evas_software_xcb_output_buffer_byte_order(Xcb_Output_Buffer *xcbob)
404{
405 return xcbob->xim->byte_order;
406}
407
408int
409evas_software_xcb_output_buffer_bit_order(Xcb_Output_Buffer *xcbob)
410{
411 return xcbob->xim->bit_order;
412}
413
414/* local functions */
415static void
416_xcbob_sync(xcb_connection_t *conn)
417{
418 free(xcb_get_input_focus_reply(conn,
419 xcb_get_input_focus_unchecked(conn), NULL));
420}
421
422static xcb_image_t *
423_xcbob_create_native(xcb_connection_t *conn, int w, int h, xcb_image_format_t format, uint8_t depth, void *base, uint32_t bytes, uint8_t *data)
424{
425 static uint8_t dpth = 0;
426 static xcb_format_t *fmt = NULL;
427 const xcb_setup_t *setup;
428 xcb_image_format_t xif;
429
430 /* NB: We cannot use xcb_image_create_native as it only creates images
431 * using MSB_FIRST, so this routine recreates that function and uses
432 * the endian-ness of the server setup */
433 setup = xcb_get_setup(conn);
434 xif = format;
435
436 if ((xif == XCB_IMAGE_FORMAT_Z_PIXMAP) && (depth == 1))
437 xif = XCB_IMAGE_FORMAT_XY_PIXMAP;
438
439 if (dpth != depth)
440 {
441 dpth = depth;
442 fmt = _xcbob_find_format(setup, depth);
443 if (!fmt) return 0;
444 }
445
446 switch (xif)
447 {
448 case XCB_IMAGE_FORMAT_XY_BITMAP:
449 if (depth != 1) return 0;
450 case XCB_IMAGE_FORMAT_XY_PIXMAP:
451 case XCB_IMAGE_FORMAT_Z_PIXMAP:
452 return xcb_image_create(w, h, xif,
453 fmt->scanline_pad,
454 fmt->depth, fmt->bits_per_pixel,
455 setup->bitmap_format_scanline_unit,
456 setup->image_byte_order,
457 setup->bitmap_format_bit_order,
458 base, bytes, data);
459 default:
460 break;
461 }
462
463 return 0;
464}
465
466static xcb_format_t *
467_xcbob_find_format(const xcb_setup_t *setup, uint8_t depth)
468{
469 xcb_format_t *fmt, *fmtend;
470
471 fmt = xcb_setup_pixmap_formats(setup);
472 fmtend = fmt + xcb_setup_pixmap_formats_length(setup);
473 for (; fmt != fmtend; ++fmt)
474 if (fmt->depth == depth)
475 return fmt;
476
477 return 0;
478}
479
480static xcb_visualtype_t *
481_xcbob_find_visual_by_id(xcb_screen_t *screen, xcb_visualid_t id)
482{
483 xcb_depth_iterator_t diter;
484 xcb_visualtype_iterator_t viter;
485
486 diter = xcb_screen_allowed_depths_iterator(screen);
487 for (; diter.rem; xcb_depth_next(&diter))
488 {
489 viter = xcb_depth_visuals_iterator(diter.data);
490 for (; viter.rem; xcb_visualtype_next(&viter))
491 {
492 if (viter.data->visual_id == id)
493 return viter.data;
494 }
495 }
496
497 return 0;
498}