#include "evas_common.h" #include "evas_engine.h" static int _xcb_err = 0; int evas_software_8_x11_x_can_do_shm(xcb_connection_t * c, xcb_screen_t * screen) { static xcb_connection_t *cached_c = NULL; static int cached_result = 0; if (c == cached_c) return cached_result; cached_c = c; if (xcb_get_extension_data(c, &xcb_shm_id)) { X_Output_Buffer *xob; xob = evas_software_8_x11_x_output_buffer_new (c, screen, screen->root_depth, (unsigned char *)NULL, 16, 16, 2, NULL); if (!xob) { cached_result = 0; return 0; } evas_software_8_x11_x_output_buffer_free(xob, 1); cached_result = 1; return 1; } cached_result = 0; return 0; } X_Output_Buffer * evas_software_8_x11_x_output_buffer_new(xcb_connection_t * c, xcb_screen_t * s, int depth, unsigned char *pal, int w, int h, int try_shm, void *data) { X_Output_Buffer *xob; xob = calloc(1, sizeof(X_Output_Buffer)); if (!xob) return NULL; xob->connection = c; xob->screen = s; xob->xim = NULL; xob->shm_info = NULL; xob->pal = pal; if (try_shm > 0) { xob->shm_info = malloc(sizeof(xcb_shm_segment_info_t)); if (xob->shm_info) { xob->shm_info->shmseg = xcb_generate_id(c); xob->xim = xcb_image_create_native(c, w, h, XCB_IMAGE_FORMAT_Z_PIXMAP, depth, NULL, ~0, NULL); if (xob->xim) { int shmid = shmget (IPC_PRIVATE, xob->xim->size, IPC_CREAT | 0777); if (shmid >= 0) { xob->shm_info->shmid = shmid; xob->shm_info->shmaddr = xob->xim->data = shmat(xob->shm_info->shmid, 0, 0); if (xob->shm_info->shmaddr) { /* * FIXME: no error mechanism */ /* XErrorHandler ph; */ /* EventHandlers eh; */ free(xcb_get_input_focus_reply (c, xcb_get_input_focus_unchecked(c), NULL)); _xcb_err = 0; /* ph = XSetErrorHandler((XErrorHandler) */ /* x_output_tmp_x_err); */ xcb_shm_attach(c, xob->shm_info->shmseg, xob->shm_info->shmid, 0); free(xcb_get_input_focus_reply (c, xcb_get_input_focus_unchecked(c), NULL)); /* XSetErrorHandler((XErrorHandler)ph); */ if (!_xcb_err) { xob->im = (Soft8_Image *) evas_cache_image_data (evas_common_soft8_image_cache_get(), w, h, (DATA32 *) xob->xim->data, 0, EVAS_COLORSPACE_GRY8); if (xob->im) xob->im->stride = xob->xim->stride / sizeof(DATA8); return xob; } } shmdt(xob->shm_info->shmaddr); shmctl(xob->shm_info->shmid, IPC_RMID, 0); } if (xob->xim) xcb_image_destroy(xob->xim); xob->xim = NULL; } if (xob->shm_info) free(xob->shm_info); xob->shm_info = NULL; } } if (try_shm > 1) return NULL; xob->xim = xcb_image_create_native(c, w, h, XCB_IMAGE_FORMAT_Z_PIXMAP, depth, NULL, ~0, NULL); if (!xob->xim) { free(xob); return NULL; } xob->data = data; if (!xob->xim->data) { xob->xim->data = malloc(xob->xim->stride * xob->xim->height); if (!xob->xim->data) { xcb_image_destroy(xob->xim); free(xob); return NULL; } } if (xob->im) evas_cache_image_drop(&xob->im->cache_entry); xob->im = (Soft8_Image *) evas_cache_image_data(evas_common_soft8_image_cache_get(), w, h, (DATA32 *) xob->xim->data, 0, EVAS_COLORSPACE_GRY8); if (xob->im) xob->im->stride = xob->xim->stride / sizeof(DATA8); return xob; } void evas_software_8_x11_x_output_buffer_free(X_Output_Buffer * xob, int sync) { if (xob->shm_info) { if (sync) free(xcb_get_input_focus_reply(xob->connection, xcb_get_input_focus_unchecked(xob-> connection), NULL)); xcb_shm_detach(xob->connection, xob->shm_info->shmseg); xcb_image_destroy(xob->xim); shmdt(xob->shm_info->shmaddr); shmctl(xob->shm_info->shmid, IPC_RMID, 0); free(xob->shm_info); } else { if (xob->data) xob->xim->data = NULL; free(xob->xim->data); xcb_image_destroy(xob->xim); } free(xob); } void evas_software_8_x11_x_output_buffer_paste(X_Output_Buffer * xob, xcb_drawable_t d, xcb_gcontext_t gc, int x, int y, int w, int h, int sync) { unsigned char *data; int i, j; if (xob->shm_info) { for (i = y; i < y + h; i++) { data = xob->xim->data + i * xob->xim->width + x; for (j = x; j < x + w; j++, data++) *data = xob->pal[*data]; } xcb_image_shm_put(xob->connection, d, gc, xob->xim, *xob->shm_info, x, y, x, y, w, h, 0); if (sync) free(xcb_get_input_focus_reply(xob->connection, xcb_get_input_focus_unchecked(xob-> connection), NULL)); } else { xcb_image_put(xob->connection, d, gc, xob->xim, x, y, 0); } } DATA8 * evas_software_8_x11_x_output_buffer_data(X_Output_Buffer * xob, int *bytes_per_line_ret) { if (bytes_per_line_ret) *bytes_per_line_ret = xob->xim->stride; return (DATA8 *) xob->xim->data; } int evas_software_8_x11_x_output_buffer_depth(X_Output_Buffer * xob) { return xob->xim->bpp; } int evas_software_8_x11_x_output_buffer_byte_order(X_Output_Buffer * xob) { return xob->xim->byte_order; } int evas_software_8_x11_x_output_buffer_bit_order(X_Output_Buffer * xob) { return xob->xim->bit_order; }