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);
}