Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
/* * QEMU Xen3d display driver * * By Chris Smowton * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "qemu-common.h" #include "console.h" #include "sysemu.h" #define MSG_UPDATE 0 #define MSG_BUFFER 1 #define MSG_INIT 2 struct pixel { char r; char g; char b; char a; }; static void send_message(int fd, char* message, int size) { int bytessent = 0; int sent; while(bytessent < size) { if((sent = send(fd, message + bytessent, size - bytessent, 0)) <= 0) { fprintf(stderr, "[Xen3d] Failed to send socket traffic to the compositor in dpy_update (return %d, errno %d)\n", sent, errno); return; } bytessent += sent; } } static void recreate_format(DisplayState* ds) { if(source_format) Hermes_FormatFree(source_format); int32 rmask, gmask, bmask, amask = 0; switch(ds->depth) { case 32: amask = 0xFF000000; // Fall-through case 24: rmask = 0x00FF0000; gmask = 0x0000FF00; bmask = 0x000000FF; break; case 16: rmask = 0x0000F800; gmask = 0x000007E0; bmask = 0x0000001F; break; default: rmask = gmask = bmask = 0; } char indexed = (char)(ds->depth == 8); source_format = Hermes_FormatNew(ds->depth, rmask, gmask, bmask, amask, indexed); if(!source_format) { fprintf(stderr, "[Xen3d] Failed to create a format (%x, %x, %x, %x, depth %d, indexed = %d)\n", rmask, gmask, bmask, amask, ds->depth, indexed); return; } } static int create_and_notify_new_buffer(int w, int h) { int size = w * h * 4; int shmid; if(shmtarget) { shmdt(shmtarget); shmtarget = 0; } key_t key = ftok("xen3d", 0); // Find a usable key while(((shmid = shmget(key, size, IPC_CREAT | IPC_EXCL | 0600)) == -1) && errno = EEXIST) key++; if(shmid == -1) { fprintf("[Xen3d] Failed to get shared memory segment\n"); return 0; } if(!(shm_target = shmat(shmid, 0, 0))) { fprintf("[Xen3d] Failed to attach shared memory segment\n"); return 0; } struct new_buffer_message message; message.opcode = MSG_BUFFER; message.width = w; message.height = h; message.shmkey = key; if(!send_message(sockfd, (char*)&message, sizeof(struct new_buffer_message))) { fprintf(fprintf, "[Xen3d] Couldn't notify remote of a new buffer\n"); shmdt(shm_target); shm_target = 0; return 0; } return 1; } static void xen3d_update(DisplayState *ds, int x, int y, int w, int h) { // printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h); // Copy and pixel-convert into shared area using Hermes // First some sanity checks: if(!shm_target) { fprintf(stderr, "xen3d_update called with no mapped shared section; discarding\n"); return; } if(!ds->data) { fprintf(stderr, "xen3d_update called with no ds->data; discarding\n"); return; } struct sembuf request; request.sem_num = 0; request.sem_op = -1; request.sem_flg = 0; if(semop(compositor_semaphore, &request, 1) == -1) { fprintf(stderr, "[Xen3d] Failed to get lock in dpy_update\n"); return; } // Locked the region we're drawing into if(!Hermes_ConverterRequest(hermes_handle, source_format, rgba32) { fprintf(stderr, "[Xen3d] ConverterRequest failed in dpy_update\n"); goto out; } if(ds->depth == 8) { if(!Hermes_ConverterPalette(hermes_handle, hermes_palette, hermes_palette)) { fprintf(stderr, "[Xen3d] Failed to set palette for conversion in dpy_update\n"); goto out; } } if(!Hermes_ConverterCopy(hermes_handle, ds->data, x, y, w, h, ds->width * (ds->depth / 8), shm_target, x, y, w, h, ds->width * 4)) { fprintf(stderr, "[Xen3d] Conversion failed in dpy_update\n"); goto out; } out: request.sem_op = 1; if(semop(compositor_semaphore, &request, 1) == -1) { fprintf(stderr, "[Xen3d] Failed to release lock in dpy_update\n"); return; } struct update_message message; message.opcode = MSG_UPDATE; message.x = x; message.y = y; message.w = w; message.h = h; if(!send_message(sockfd, (char*)&message, sizeof(struct update_message))) { fprintf(stderr, "[Xen3d] Failed to send update notification to the compositor\n"); return; } } static void xen3d_setdata(DisplayState *ds, void *pixels) { if(my_buffer) { free(my_buffer); my_buffer = 0; } if(hermes_palette) { Hermes_PaletteReturn(hermes_palette); hermes_palette = 0; } if (ds->depth == 8 && ds->palette != NULL) { hermes_palette = Hermes_PaletteInstance(); if(!hermes_palette) { fprintf(stderr, "[Xen3d] Could not create a Hermes palette in dpy_setdata\n"); goto out; } int32* palette = Hermes_PaletteGet(hermes_palette); if(!palette) { fprintf(stderr, "[Xen3d] Could not map palette in dpy_setdata\n"); goto out; } int i; for (i = 0; i < 256; i++) { uint8_t rgb = ds->palette[i] >> 16; struct pixel* entry = (struct pixel*)&(palette[i]); entry->r = ((rgb & 0xe0) >> 5) * 255 / 7; entry->g = ((rgb & 0x1c) >> 2) * 255 / 7; entry->b = (rgb & 0x3) * 255 / 3; entry->a = 0xFF; } Hermes_PaletteInvalidateCache(hermes_handle); } recreate_format(ds); create_and_notify_new_buffer(ds->width, ds->height); out: ds->data = pixels; } static void xen3d_resize_shared(DisplayState *ds, int w, int h, int depth, int linesize, void *pixels) { // Meaning: Use this pixels as the new ds->data, where it has the following dimensions // printf("resizing to %d %d\n", w, h); if (!depth || !ds->depth) { ds->shared_buf = 0; } else { ds->shared_buf = 1; ds->depth = depth; } ds->width = w; ds->height = h; if(mybuffer) { free(mybuffer); mybuffer = 0; } if (!ds->shared_buf) { // I should own the buffer. Create one and set ->data to that. ds->depth = 32; ds->bgr = 0; mybuffer = malloc(w * h * 4); if(!mybuffer) { fprintf("[Xen3d] malloc failed in dpy_resize_shared, trying for a display of %dx%dx32\n", w, h); ds->data = 0; goto out; } ds->data = mybuffer; ds->linesize = w * 4; recreate_format(ds); create_and_notify_new_buffer(w, h); } else { ds->linesize = linesize; ds->dpy_setdata(ds, pixels); } } static void xen3d_resize(DisplayState *ds, int w, int h) { xen3d_resize_shared(ds, w, h, 0, w * (ds->depth / 8), NULL); } /* generic keyboard conversion */ /* #include "keymaps.c" static kbd_layout_t *kbd_layout = NULL; static uint8_t sdl_keyevent_to_keycode_generic(const SDL_KeyboardEvent *ev) { int keysym;*/ /* workaround for X11+SDL bug with AltGR */ /* keysym = ev->keysym.sym; if (keysym == 0 && ev->keysym.scancode == 113) keysym = SDLK_MODE;*/ /* For Japanese key '\' and '|' */ /* if (keysym == 92 && ev->keysym.scancode == 133) { keysym = 0xa5; } return keysym2scancode(kbd_layout, keysym); }*/ /* specific keyboard conversions from scan codes */ /* #if defined(_WIN32) static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev) { return ev->keysym.scancode; } #else static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev) { int keycode; keycode = ev->keysym.scancode; if (keycode < 9) { keycode = 0; } else if (keycode < 97) { keycode -= 8; *//* just an offset */ /* } else if (keycode < 212) {*/ /* use conversion table */ /* keycode = _translate_keycode(keycode - 97); } else { keycode = 0; } return keycode; } #endif static void reset_keys(void) { int i; for(i = 0; i < 256; i++) { if (modifiers_state[i]) { if (i & 0x80) kbd_put_keycode(0xe0); kbd_put_keycode(i | 0x80); modifiers_state[i] = 0; } } } static void sdl_process_key(SDL_KeyboardEvent *ev) { int keycode, v; if (ev->keysym.sym == SDLK_PAUSE) {*/ /* specific case */ /* v = 0; if (ev->type == SDL_KEYUP) v |= 0x80; kbd_put_keycode(0xe1); kbd_put_keycode(0x1d | v); kbd_put_keycode(0x45 | v); return; } if (kbd_layout) { keycode = sdl_keyevent_to_keycode_generic(ev); } else { keycode = sdl_keyevent_to_keycode(ev); } switch(keycode) { case 0x00:*/ /* sent when leaving window: reset the modifiers state */ /* reset_keys(); return;*/ // case 0x2a: /* Left Shift */ // case 0x36: /* Right Shift */ // case 0x1d: /* Left CTRL */ // case 0x9d: /* Right CTRL */ // case 0x38: /* Left ALT */ // case 0xb8: /* Right ALT */ /* if (ev->type == SDL_KEYUP) modifiers_state[keycode] = 0; else modifiers_state[keycode] = 1; break;*/ // case 0x45: /* num lock */ // case 0x3a: /* caps lock */ /* SDL does not send the key up event, so we generate it */ /* kbd_put_keycode(keycode); kbd_put_keycode(keycode | 0x80); return; }*/ /* now send the key code */ /* if (keycode & 0x80) kbd_put_keycode(0xe0); if (ev->type == SDL_KEYUP) kbd_put_keycode(keycode | 0x80); else kbd_put_keycode(keycode & 0x7f); } static void sdl_update_caption(void) { char buf[1024]; strcpy(buf, domain_name); if (!vm_running) { strcat(buf, " [Stopped]"); } if (gui_grab) { if (!alt_grab) strcat(buf, " - Press Ctrl-Alt to exit grab"); else strcat(buf, " - Press Ctrl-Alt-Shift to exit grab"); } SDL_WM_SetCaption(buf, domain_name); } static void sdl_hide_cursor(void) { if (!cursor_hide) return; if (kbd_mouse_is_absolute()) { SDL_ShowCursor(1); SDL_SetCursor(sdl_cursor_hidden); } else { SDL_ShowCursor(0); } } static void sdl_show_cursor(void) { if (!cursor_hide) return; if (!kbd_mouse_is_absolute()) { SDL_ShowCursor(1); SDL_SetCursor(sdl_cursor_normal); } } static void sdl_grab_start(void) { sdl_hide_cursor(); SDL_WM_GrabInput(SDL_GRAB_ON); gui_grab = 1; sdl_update_caption(); } static void sdl_grab_end(void) { SDL_WM_GrabInput(SDL_GRAB_OFF); gui_grab = 0; sdl_show_cursor(); sdl_update_caption(); } static void sdl_send_mouse_event(int dx, int dy, int dz, int state) { int buttons = 0; if (state & SDL_BUTTON(SDL_BUTTON_LEFT)) buttons |= MOUSE_EVENT_LBUTTON; if (state & SDL_BUTTON(SDL_BUTTON_RIGHT)) buttons |= MOUSE_EVENT_RBUTTON; if (state & SDL_BUTTON(SDL_BUTTON_MIDDLE)) buttons |= MOUSE_EVENT_MBUTTON; if (kbd_mouse_is_absolute()) { if (!absolute_enabled) { sdl_hide_cursor(); if (gui_grab) { sdl_grab_end(); } absolute_enabled = 1; } SDL_GetMouseState(&dx, &dy); dx = dx * 0x7FFF / (screen->w - 1); dy = dy * 0x7FFF / (screen->h - 1); } else if (absolute_enabled) { sdl_show_cursor(); absolute_enabled = 0; } kbd_mouse_event(dx, dy, dz, buttons); } static void toggle_full_screen(DisplayState *ds) { gui_fullscreen = !gui_fullscreen; sdl_resize_shared(ds, ds->width, ds->height, ds->depth, ds->linesize, ds->data); if (gui_fullscreen) { gui_saved_grab = gui_grab; sdl_grab_start(); } else { if (!gui_saved_grab) sdl_grab_end(); } vga_hw_invalidate(); vga_hw_update(); }*/ static void xen3d_refresh(DisplayState *ds) { // In future: pull key and mouse events out of the compositor and feed them through } static void xen3d_cleanup(void) { if(mybuffer) free(mybuffer); Hermes_ConverterReturn(hermes_handle); if(hermes_palette) Hermes_PaletteReturn(hermes_palette); if(source_format) Hermes_FormatFree(source_format); if(rgba32) Hermes_FormatFree(rgba32); if(!Hermes_Done()) { fprintf(stderr, "[Xen3d] Hermes_Done returned an error; refcounting mistake?\n"); } close(sockfd); } void xen3d_display_init(DisplayState *ds) { if(!Hermes_Init()) { fprintf(stderr, "[Xen3d] Failed to initialise Hermes pixel-conversion library\n"); return; } if(!(hermes_handle = Hermes_ConverterInstance(0))) { fprintf(stderr, "[Xen3d] Failed to get Hermes converter\n"); Hermes_Done(); return; } rgba32 = Hermes_FormatNew(32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000, 0); if(!rgba32) { fprintf(stderr, "[Xen3d] Failed to get Hermes RGBA format\n"); Hermes_ConverterReturn(hermes_handle); Hermes_Done(); return; } key_t key = ftok("xen3d", 0); while(((compositor_semaphore = semget(key, 1, IPC_CREAT | IPC_EXCL | 0600)) == -1) && errno == EEXIST) key++; if(compositor_semaphore == -1) { fprintf(stderr, "[Xen3d] Failed to get semaphore set\n"); return; } union semun arg; arg.val = 1; if(semctl(compositor_semaphore, 0, IPC_SETVAL, arg) == -1) { fprintf(stderr, "[Xen3d] Couldn't set semaphore initial value\n"); semctl(compositor_semaphore, 0, IPC_RMID, arg); Hermes_FormatFree(rgba32); Hermes_ConverterReturn(hermes_handle); Hermes_Done(); return; } if((sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) { fprintf("[Xen3d] Couldn't create a Unix domain socket\n"); semctl(compositor_semaphore, 0, IPC_RMID, arg); Hermes_FormatFree(rgba32); Hermes_ConverterReturn(hermes_handle); Hermes_Done(); return; } struct sockaddr_un sun; sun.sun_family = AF_UNIX; strcpy(sun.sun_path, "/var/run/xen3d-socket"); if(connect(sockfd, &sun, sizeof(sun.sun_family) + strlen(sun.sun_path)) < 0) { fprintf("[Xen3d] Couldn't connect to /var/run/xen3d-socket\n"); semctl(compositor_semaphore, 0, IPC_RMID, arg); Hermes_FormatFree(rgba32); Hermes_ConverterReturn(hermes_handle); Hermes_Done(); return; } struct init_message message; message.opcode = MSG_INIT; message.sem_key = key; if(!send_message(sockfd, (char*)&message, sizeof(struct init_message))) { fprintf("[Xen3d] Couldn't connect to /var/run/xen3d-socket\n"); semctl(compositor_semaphore, 0, IPC_RMID, arg); Hermes_FormatFree(rgba32); Hermes_ConverterReturn(hermes_handle); Hermes_Done(); return; } // Everything worked! ds->dpy_update = xen3d_update; ds->dpy_resize = xen3d_resize; ds->dpy_resize_shared = xen3d_resize_shared; ds->dpy_refresh = xen3d_refresh; ds->dpy_setdata = xen3d_setdata; xen3d_resize(ds, 640, 400); }