Пример #1
0
void gd_gl_area_switch(DisplayChangeListener *dcl,
                       DisplaySurface *surface)
{
    VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
    bool resized = true;

    trace_gd_switch(vc->label, surface_width(surface), surface_height(surface));

    if (vc->gfx.ds &&
        surface_width(vc->gfx.ds) == surface_width(surface) &&
        surface_height(vc->gfx.ds) == surface_height(surface)) {
        resized = false;
    }

    if (vc->gfx.gls) {
        gtk_gl_area_make_current(GTK_GL_AREA(vc->gfx.drawing_area));
        surface_gl_destroy_texture(vc->gfx.gls, vc->gfx.ds);
        surface_gl_create_texture(vc->gfx.gls, surface);
    }
    vc->gfx.ds = surface;

    if (resized) {
        gd_update_windowsize(vc);
    }
}
Пример #2
0
static void sdl_switch(DisplayChangeListener *dcl,
                       DisplaySurface *new_surface)
{
    PixelFormat pf;

    /* temporary hack: allows to call sdl_switch to handle scaling changes */
    if (new_surface) {
        surface = new_surface;
    }
    pf = qemu_pixelformat_from_pixman(surface->format);

    if (!scaling_active) {
        do_sdl_resize(surface_width(surface), surface_height(surface), 0);
    } else if (real_screen->format->BitsPerPixel !=
               surface_bits_per_pixel(surface)) {
        do_sdl_resize(real_screen->w, real_screen->h,
                      surface_bits_per_pixel(surface));
    }

    if (guest_screen != NULL) {
        SDL_FreeSurface(guest_screen);
    }

#ifdef DEBUG_SDL
    printf("SDL: Creating surface with masks: %08x %08x %08x %08x\n",
           pf.rmask, pf.gmask, pf.bmask, pf.amask);
#endif

    guest_screen = SDL_CreateRGBSurfaceFrom
        (surface_data(surface),
         surface_width(surface), surface_height(surface),
         surface_bits_per_pixel(surface), surface_stride(surface),
         pf.rmask, pf.gmask,
         pf.bmask, pf.amask);
}
Пример #3
0
void sdl2_gl_switch(DisplayChangeListener *dcl,
                    DisplaySurface *new_surface)
{
    struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl);
    DisplaySurface *old_surface = scon->surface;

    assert(scon->opengl);

    SDL_GL_MakeCurrent(scon->real_window, scon->winctx);
    surface_gl_destroy_texture(scon->gls, scon->surface);

    scon->surface = new_surface;

    if (!new_surface) {
        console_gl_fini_context(scon->gls);
        scon->gls = NULL;
        sdl2_window_destroy(scon);
        return;
    }

    if (!scon->real_window) {
        sdl2_window_create(scon);
        scon->gls = console_gl_init_context();
    } else if (old_surface &&
               ((surface_width(old_surface)  != surface_width(new_surface)) ||
                (surface_height(old_surface) != surface_height(new_surface)))) {
        sdl2_window_resize(scon);
    }

    surface_gl_create_texture(scon->gls, scon->surface);
}
Пример #4
0
static void sdl_switch(DisplayChangeListener *dcl,
                       DisplaySurface *new_surface)
{

    /* temporary hack: allows to call sdl_switch to handle scaling changes */
    if (new_surface) {
        surface = new_surface;
    }

    if (!scaling_active) {
        do_sdl_resize(surface_width(surface), surface_height(surface), 0);
    } else if (real_screen->format->BitsPerPixel !=
               surface_bits_per_pixel(surface)) {
        do_sdl_resize(real_screen->w, real_screen->h,
                      surface_bits_per_pixel(surface));
    }

    if (guest_screen != NULL) {
        SDL_FreeSurface(guest_screen);
    }
    guest_screen = SDL_CreateRGBSurfaceFrom
        (surface_data(surface),
         surface_width(surface), surface_height(surface),
         surface_bits_per_pixel(surface), surface_stride(surface),
         surface->pf.rmask, surface->pf.gmask,
         surface->pf.bmask, surface->pf.amask);
}
Пример #5
0
void sdl2_2d_switch(DisplayChangeListener *dcl,
                    DisplaySurface *new_surface)
{
    struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl);
    DisplaySurface *old_surface = scon->surface;
    int format = 0;

    assert(!scon->opengl);

    scon->surface = new_surface;

    if (scon->texture) {
        SDL_DestroyTexture(scon->texture);
        scon->texture = NULL;
    }

    if (!new_surface) {
        sdl2_window_destroy(scon);
        return;
    }

    if (!scon->real_window) {
        sdl2_window_create(scon);
    } else if (old_surface &&
               ((surface_width(old_surface)  != surface_width(new_surface)) ||
                (surface_height(old_surface) != surface_height(new_surface)))) {
        sdl2_window_resize(scon);
    }

    SDL_RenderSetLogicalSize(scon->real_renderer,
                             surface_width(new_surface),
                             surface_height(new_surface));

    switch (surface_format(scon->surface)) {
    case PIXMAN_x1r5g5b5:
        format = SDL_PIXELFORMAT_ARGB1555;
        break;
    case PIXMAN_r5g6b5:
        format = SDL_PIXELFORMAT_RGB565;
        break;
    case PIXMAN_x8r8g8b8:
        format = SDL_PIXELFORMAT_ARGB8888;
        break;
    case PIXMAN_r8g8b8x8:
        format = SDL_PIXELFORMAT_RGBA8888;
        break;
    case PIXMAN_b8g8r8x8:
        format = SDL_PIXELFORMAT_BGRX8888;
        break;
    default:
        g_assert_not_reached();
    }
    scon->texture = SDL_CreateTexture(scon->real_renderer, format,
                                      SDL_TEXTUREACCESS_STREAMING,
                                      surface_width(new_surface),
                                      surface_height(new_surface));
    sdl2_2d_redraw(scon);
}
Пример #6
0
/*
 * Send a mouse event from the client to the guest OS
 *
 * The QEMU mouse can be in either relative, or absolute mode.
 * Movement is sent separately from button state, which has to
 * be encoded as virtual key events. We also don't actually get
 * given any button up/down events, so have to track changes in
 * the button state.
 */
static void xenfb_mouse_event(void *opaque,
			      int dx, int dy, int dz, int button_state)
{
    struct XenInput *xenfb = opaque;
    DisplaySurface *surface = qemu_console_surface(xenfb->c.con);
    int dw = surface_width(surface);
    int dh = surface_height(surface);
    int i;

    trace_xenfb_mouse_event(opaque, dx, dy, dz, button_state,
                            xenfb->abs_pointer_wanted);
    if (xenfb->abs_pointer_wanted)
	xenfb_send_position(xenfb,
			    dx * (dw - 1) / 0x7fff,
			    dy * (dh - 1) / 0x7fff,
			    dz);
    else
	xenfb_send_motion(xenfb, dx, dy, dz);

    for (i = 0 ; i < 8 ; i++) {
	int lastDown = xenfb->button_state & (1 << i);
	int down = button_state & (1 << i);
	if (down == lastDown)
	    continue;

	if (xenfb_send_key(xenfb, down, BTN_LEFT+i) < 0)
	    return;
    }
    xenfb->button_state = button_state;
}
Пример #7
0
static void egl_scanout_flush(DisplayChangeListener *dcl,
                              uint32_t x, uint32_t y,
                              uint32_t w, uint32_t h)
{
    egl_dpy *edpy = container_of(dcl, egl_dpy, dcl);

    if (!edpy->guest_fb.texture || !edpy->ds) {
        return;
    }
    assert(surface_width(edpy->ds)  == edpy->guest_fb.width);
    assert(surface_height(edpy->ds) == edpy->guest_fb.height);
    assert(surface_format(edpy->ds) == PIXMAN_x8r8g8b8);

    if (edpy->cursor_fb.texture) {
        /* have cursor -> render using textures */
        egl_texture_blit(edpy->gls, &edpy->blit_fb, &edpy->guest_fb,
                         !edpy->y_0_top);
        egl_texture_blend(edpy->gls, &edpy->blit_fb, &edpy->cursor_fb,
                          !edpy->y_0_top, edpy->pos_x, edpy->pos_y);
    } else {
        /* no cursor -> use simple framebuffer blit */
        egl_fb_blit(&edpy->blit_fb, &edpy->guest_fb, edpy->y_0_top);
    }

    egl_fb_read(surface_data(edpy->ds), &edpy->blit_fb);
    dpy_gfx_update(edpy->dcl.con, x, y, w, h);
}
Пример #8
0
void sdl2_window_create(struct sdl2_console *scon)
{
    int flags = 0;

    if (!scon->surface) {
        return;
    }
    assert(!scon->real_window);

    if (gui_fullscreen) {
        flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
    } else {
        flags |= SDL_WINDOW_RESIZABLE;
    }
    if (scon->hidden) {
        flags |= SDL_WINDOW_HIDDEN;
    }

    scon->real_window = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED,
                                         SDL_WINDOWPOS_UNDEFINED,
                                         surface_width(scon->surface),
                                         surface_height(scon->surface),
                                         flags);
    scon->real_renderer = SDL_CreateRenderer(scon->real_window, -1, 0);
    if (scon->opengl) {
        scon->winctx = SDL_GL_GetCurrentContext();
    }
    sdl_update_caption(scon);
}
Пример #9
0
void gd_egl_draw(VirtualConsole *vc)
{
    GdkWindow *window;
    int ww, wh;

    if (!vc->gfx.gls) {
        return;
    }

    window = gtk_widget_get_window(vc->gfx.drawing_area);
    ww = gdk_window_get_width(window);
    wh = gdk_window_get_height(window);

    if (vc->gfx.scanout_mode) {
        gd_egl_scanout_flush(&vc->gfx.dcl, 0, 0, vc->gfx.w, vc->gfx.h);

        vc->gfx.scale_x = (double)ww / vc->gfx.w;
        vc->gfx.scale_y = (double)wh / vc->gfx.h;
    } else {
        if (!vc->gfx.ds) {
            return;
        }
        eglMakeCurrent(qemu_egl_display, vc->gfx.esurface,
                       vc->gfx.esurface, vc->gfx.ectx);

        surface_gl_setup_viewport(vc->gfx.gls, vc->gfx.ds, ww, wh);
        surface_gl_render_texture(vc->gfx.gls, vc->gfx.ds);

        eglSwapBuffers(qemu_egl_display, vc->gfx.esurface);

        vc->gfx.scale_x = (double)ww / surface_width(vc->gfx.ds);
        vc->gfx.scale_y = (double)wh / surface_height(vc->gfx.ds);
    }
}
Пример #10
0
void surface_gl_create_texture(ConsoleGLState *gls,
                               DisplaySurface *surface)
{
    assert(gls);
    assert(surface_stride(surface) % surface_bytes_per_pixel(surface) == 0);

    switch (surface->format) {
    case PIXMAN_BE_b8g8r8x8:
    case PIXMAN_BE_b8g8r8a8:
        surface->glformat = GL_BGRA_EXT;
        surface->gltype = GL_UNSIGNED_BYTE;
        break;
    case PIXMAN_r5g6b5:
        surface->glformat = GL_RGB;
        surface->gltype = GL_UNSIGNED_SHORT_5_6_5;
        break;
    default:
        g_assert_not_reached();
    }

    glGenTextures(1, &surface->texture);
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, surface->texture);
    glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT,
                  surface_stride(surface) / surface_bytes_per_pixel(surface));
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
                 surface_width(surface),
                 surface_height(surface),
                 0, surface->glformat, surface->gltype,
                 surface_data(surface));

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
Пример #11
0
static void toggle_full_screen(void)
{
    int width = surface_width(surface);
    int height = surface_height(surface);
    int bpp = surface_bits_per_pixel(surface);

    gui_fullscreen = !gui_fullscreen;
    if (gui_fullscreen) {
        gui_saved_width = real_screen->w;
        gui_saved_height = real_screen->h;
        gui_saved_scaling = scaling_active;

        do_sdl_resize(width, height, bpp);
        scaling_active = 0;

        gui_saved_grab = gui_grab;
        sdl_grab_start();
    } else {
        if (gui_saved_scaling) {
            sdl_scale(gui_saved_width, gui_saved_height);
        } else {
            do_sdl_resize(width, height, 0);
        }
        if (!gui_saved_grab || !qemu_console_is_graphic(NULL)) {
            sdl_grab_end();
        }
    }
    graphic_hw_invalidate(NULL);
    graphic_hw_update(NULL);
}
Пример #12
0
static void vigs_hw_update(void *opaque)
{
    VIGSState *s = opaque;
    DisplaySurface *ds = qemu_console_surface(s->con);

    if (!surface_data(ds)) {
        return;
    }

    if (vigs_server_update_display(s->server, s->invalidate_cnt)) {
        /*
         * 'vigs_server_update_display' could have updated the surface,
         * so fetch it again.
         */
        ds = qemu_console_surface(s->con);

        dpy_gfx_update(s->con, 0, 0, surface_width(ds), surface_height(ds));
    }

    if (s->invalidate_cnt > 0) {
        s->invalidate_cnt--;
    }

    if (s->reg_con & VIGS_REG_CON_VBLANK_ENABLE) {
        s->reg_int |= VIGS_REG_INT_VBLANK_PENDING;
        vigs_update_irq(s);
    }
}
Пример #13
0
static void sdl_switch(DisplayChangeListener *dcl,
                       DisplaySurface *new_surface)
{
    struct sdl2_state *scon = container_of(dcl, struct sdl2_state, dcl);
    int format = 0;
    int idx = scon->idx;
    DisplaySurface *old_surface = scon->surface;

    /* temporary hack: allows to call sdl_switch to handle scaling changes */
    if (new_surface) {
        scon->surface = new_surface;
    }

    if (!new_surface && idx > 0) {
        scon->surface = NULL;
    }

    if (new_surface == NULL) {
        do_sdl_resize(scon, 0, 0, 0);
    } else {
        do_sdl_resize(scon, surface_width(scon->surface),
                      surface_height(scon->surface), 0);
    }

    if (old_surface && scon->texture) {
        SDL_DestroyTexture(scon->texture);
        scon->texture = NULL;
    }

    if (new_surface) {
        if (!scon->texture) {
            if (surface_bits_per_pixel(scon->surface) == 16) {
                format = SDL_PIXELFORMAT_RGB565;
            } else if (surface_bits_per_pixel(scon->surface) == 32) {
                format = SDL_PIXELFORMAT_ARGB8888;
            }

            scon->texture = SDL_CreateTexture(scon->real_renderer, format,
                                              SDL_TEXTUREACCESS_STREAMING,
                                              surface_width(new_surface),
                                              surface_height(new_surface));
        }
    }
}
Пример #14
0
void sdl2_window_resize(struct sdl2_console *scon)
{
    if (!scon->real_window) {
        return;
    }

    SDL_SetWindowSize(scon->real_window,
                      surface_width(scon->surface),
                      surface_height(scon->surface));
}
Пример #15
0
void sdl2_2d_redraw(struct sdl2_console *scon)
{
    assert(!scon->opengl);

    if (!scon->surface) {
        return;
    }
    sdl2_2d_update(&scon->dcl, 0, 0,
                   surface_width(scon->surface),
                   surface_height(scon->surface));
}
Пример #16
0
static void vigs_dpy_resize(void *user_data,
                            uint32_t width,
                            uint32_t height)
{
    VIGSState *s = user_data;
    DisplaySurface *ds = qemu_console_surface(s->con);

    if ((width != surface_width(ds)) ||
        (height != surface_height(ds))) {
        qemu_console_resize(s->con, width, height);
    }
}
/* Console hooks */
void goldfish_fb_set_rotation(int rotation)
{
    DeviceState *dev = qdev_find_recursive(sysbus_get_default(), TYPE_GOLDFISH_FB);
    if (dev) {
        struct goldfish_fb_state *s = GOLDFISH_FB(dev);
        DisplaySurface *ds = qemu_console_surface(s->con);
        s->rotation = rotation;
        s->need_update = 1;
        qemu_console_resize(s->con, surface_height(ds), surface_width(ds));
    } else {
        fprintf(stderr,"%s: unable to find FB dev\n", __func__);
    }
}
Пример #18
0
static void qemu_spice_create_update(SimpleSpiceDisplay *ssd)
{
    static const int blksize = 32;
    int blocks = (surface_width(ssd->ds) + blksize - 1) / blksize;
    int dirty_top[blocks];
    int y, yoff, x, xoff, blk, bw;
    int bpp = surface_bytes_per_pixel(ssd->ds);
    uint8_t *guest, *mirror;

    if (qemu_spice_rect_is_empty(&ssd->dirty)) {
        return;
    };

    if (ssd->surface == NULL) {
        ssd->surface = pixman_image_ref(ssd->ds->image);
        ssd->mirror  = qemu_pixman_mirror_create(ssd->ds->format,
                                                 ssd->ds->image);
    }

    for (blk = 0; blk < blocks; blk++) {
        dirty_top[blk] = -1;
    }

    guest = surface_data(ssd->ds);
    mirror = (void *)pixman_image_get_data(ssd->mirror);
    for (y = ssd->dirty.top; y < ssd->dirty.bottom; y++) {
        yoff = y * surface_stride(ssd->ds);
        for (x = ssd->dirty.left; x < ssd->dirty.right; x += blksize) {
            xoff = x * bpp;
            blk = x / blksize;
            bw = MIN(blksize, ssd->dirty.right - x);
            if (memcmp(guest + yoff + xoff,
                       mirror + yoff + xoff,
                       bw * bpp) == 0) {
                if (dirty_top[blk] != -1) {
                    QXLRect update = {
                        .top    = dirty_top[blk],
                        .bottom = y,
                        .left   = x,
                        .right  = x + bw,
                    };
                    qemu_spice_create_one_update(ssd, &update);
                    dirty_top[blk] = -1;
                }
            } else {
                if (dirty_top[blk] == -1) {
                    dirty_top[blk] = y;
                }
            }
        }
    }
Пример #19
0
static void jazz_led_update_display(void *opaque)
{
    LedState *s = opaque;
    DisplaySurface *surface = qemu_console_surface(s->con);
    uint8_t *d1;
    uint32_t color_segment, color_led;
    int y, bpp;

    if (s->state & REDRAW_BACKGROUND) {
        /* clear screen */
        bpp = (surface_bits_per_pixel(surface) + 7) >> 3;
        d1 = surface_data(surface);
        for (y = 0; y < surface_height(surface); y++) {
            memset(d1, 0x00, surface_width(surface) * bpp);
            d1 += surface_stride(surface);
        }
    }
Пример #20
0
void sdl2_2d_update(DisplayChangeListener *dcl,
                    int x, int y, int w, int h)
{
    struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl);
    DisplaySurface *surf = qemu_console_surface(dcl->con);
    SDL_Rect rect;

    assert(!scon->opengl);

    if (!surf) {
        return;
    }
    if (!scon->texture) {
        return;
    }

    /*
     * SDL2 seems to do some double-buffering, and trying to only
     * update the changed areas results in only one of the two buffers
     * being updated.  Which flickers alot.  So lets not try to be
     * clever do a full update every time ...
     */
#if 0
    rect.x = x;
    rect.y = y;
    rect.w = w;
    rect.h = h;
#else
    rect.x = 0;
    rect.y = 0;
    rect.w = surface_width(surf);
    rect.h = surface_height(surf);
#endif

    SDL_UpdateTexture(scon->texture, NULL, surface_data(surf),
                      surface_stride(surf));
#if defined( __ANDROID__) && defined (__LIMBO_SDL_FORCE_HARDWARE_RENDERING__)
	//Android OPENGL ES needs full screen redraw
    SDL_SetRenderDrawColor( scon->real_renderer, 0, 0, 0, 255 );
    SDL_RenderClear( scon->real_renderer );
    SDL_RenderCopy(scon->real_renderer, scon->texture, NULL, NULL);
#else
    SDL_RenderCopy(scon->real_renderer, scon->texture, &rect, &rect);
#endif //__ANDROID__
    SDL_RenderPresent(scon->real_renderer);
}
static int  goldfish_fb_load(QEMUFile*  f, void*  opaque, int  version_id)
{
    struct goldfish_fb_state*  s   = opaque;
    int                        ret = -1;
    int                        ds_w, ds_h, ds_pitch, ds_rot;

    if (version_id != GOLDFISH_FB_SAVE_VERSION)
        goto Exit;

    ds_w     = qemu_get_be32(f);
    ds_h     = qemu_get_be32(f);
    ds_pitch = qemu_get_be32(f);
    ds_rot   = qemu_get_byte(f);

    DisplaySurface *ds = qemu_console_surface(s->con);

    if (surface_width(ds) != ds_w ||
        surface_height(ds) != ds_h ||
        surface_stride(ds) != ds_pitch ||
        ds_rot != 0)
    {
        /* XXX: We should be able to force a resize/rotation from here ? */
        fprintf(stderr, "%s: framebuffer dimensions mismatch\n", __FUNCTION__);
        goto Exit;
    }

    s->fb_base      = qemu_get_be32(f);
    s->base_valid   = qemu_get_byte(f);
    s->need_update  = qemu_get_byte(f);
    s->need_int     = qemu_get_byte(f);
    s->blank        = qemu_get_byte(f);
    s->int_status   = qemu_get_be32(f);
    s->int_enable   = qemu_get_be32(f);
    s->rotation     = qemu_get_be32(f);
    s->dpi          = qemu_get_be32(f);
    s->format       = qemu_get_be32(f);

    /* force a refresh */
    s->need_update = 1;

    ret = 0;
Exit:
    return ret;
}
static void goldfish_fb_save(QEMUFile*  f, void*  opaque)
{
    struct goldfish_fb_state*  s = opaque;

    DisplaySurface *ds = qemu_console_surface(s->con);

    qemu_put_be32(f, surface_width(ds));
    qemu_put_be32(f, surface_height(ds));
    qemu_put_be32(f, surface_stride(ds));
    qemu_put_byte(f, 0);

    qemu_put_be32(f, s->fb_base);
    qemu_put_byte(f, s->base_valid);
    qemu_put_byte(f, s->need_update);
    qemu_put_byte(f, s->need_int);
    qemu_put_byte(f, s->blank);
    qemu_put_be32(f, s->int_status);
    qemu_put_be32(f, s->int_enable);
    qemu_put_be32(f, s->rotation);
    qemu_put_be32(f, s->dpi);
    qemu_put_be32(f, s->format);
}
Пример #23
0
void surface_gl_setup_viewport(ConsoleGLState *gls,
                               DisplaySurface *surface,
                               int ww, int wh)
{
    int gw, gh, stripe;
    float sw, sh;

    assert(gls);

    gw = surface_width(surface);
    gh = surface_height(surface);

    sw = (float)ww/gw;
    sh = (float)wh/gh;
    if (sw < sh) {
        stripe = wh - wh*sw/sh;
        glViewport(0, stripe / 2, ww, wh - stripe);
    } else {
        stripe = ww - ww*sh/sw;
        glViewport(stripe / 2, 0, ww - stripe, wh);
    }
}
Пример #24
0
void sdl2_2d_update(DisplayChangeListener *dcl,
                    int x, int y, int w, int h)
{
    struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl);
    DisplaySurface *surf = qemu_console_surface(dcl->con);
    SDL_Rect rect;

    assert(!scon->opengl);

    if (!surf) {
        return;
    }
    if (!scon->texture) {
        return;
    }

    /*
     * SDL2 seems to do some double-buffering, and trying to only
     * update the changed areas results in only one of the two buffers
     * being updated.  Which flickers alot.  So lets not try to be
     * clever do a full update every time ...
     */
#if 0
    rect.x = x;
    rect.y = y;
    rect.w = w;
    rect.h = h;
#else
    rect.x = 0;
    rect.y = 0;
    rect.w = surface_width(surf);
    rect.h = surface_height(surf);
#endif

    SDL_UpdateTexture(scon->texture, NULL, surface_data(surf),
                      surface_stride(surf));
    SDL_RenderCopy(scon->real_renderer, scon->texture, &rect, &rect);
    SDL_RenderPresent(scon->real_renderer);
}
Пример #25
0
static void tc6393xb_update_display(void *opaque)
{
    TC6393xbState *s = opaque;
    DisplaySurface *surface = qemu_console_surface(s->con);
    int full_update;

    if (s->scr_width == 0 || s->scr_height == 0)
        return;

    full_update = 0;
    if (s->blanked != s->blank) {
        s->blanked = s->blank;
        full_update = 1;
    }
    if (s->scr_width != surface_width(surface) ||
        s->scr_height != surface_height(surface)) {
        qemu_console_resize(s->con, s->scr_width, s->scr_height);
        full_update = 1;
    }
    if (s->blanked)
        tc6393xb_draw_blank(s, full_update);
    else
        tc6393xb_draw_graphic(s, full_update);
}
static void goldfish_fb_update_display(void *opaque)
{
    struct goldfish_fb_state *s = (struct goldfish_fb_state *)opaque;
    DisplaySurface *ds = qemu_console_surface(s->con);
    int full_update = 0;

    if (!s || !s->con || surface_bits_per_pixel(ds) == 0 || !s->fb_base)
        return;

    if((s->int_enable & FB_INT_VSYNC) && !(s->int_status & FB_INT_VSYNC)) {
        s->int_status |= FB_INT_VSYNC;
        qemu_irq_raise(s->irq);
    }

    if(s->need_update) {
        full_update = 1;
        if(s->need_int) {
            s->int_status |= FB_INT_BASE_UPDATE_DONE;
            if(s->int_enable & FB_INT_BASE_UPDATE_DONE)
                qemu_irq_raise(s->irq);
        }
        s->need_int = 0;
        s->need_update = 0;
    }

    int dest_width = surface_width(ds);
    int dest_height = surface_height(ds);
    int dest_pitch = surface_stride(ds);
    int ymin, ymax;

#if STATS
    if (full_update)
        stats_full_updates += 1;
    if (++stats_counter == 120) {
        stats_total               += stats_counter;
        stats_total_full_updates  += stats_full_updates;

        trace_goldfish_fb_update_stats(stats_full_updates*100.0/stats_counter,
                stats_total_full_updates*100.0/stats_total );

        stats_counter      = 0;
        stats_full_updates = 0;
    }
#endif /* STATS */

    if (s->blank)
    {
        void *dst_line = surface_data(ds);
        memset( dst_line, 0, dest_height*dest_pitch );
        ymin = 0;
        ymax = dest_height-1;
    }
    else
    {
        SysBusDevice *dev = SYS_BUS_DEVICE(opaque);
        MemoryRegion *address_space = sysbus_address_space(dev);
        int src_width, src_height;
        int dest_row_pitch, dest_col_pitch;
        drawfn fn;

        /* The source framebuffer is always read in a linear fashion,
         * we achieve rotation by altering the destination
         * step-per-pixel.
         */
        switch (s->rotation) {
        case 0: /* Normal, native landscape view */
            src_width = dest_width;
            src_height = dest_height;
            dest_row_pitch = surface_stride(ds);
            dest_col_pitch = surface_bytes_per_pixel(ds);
            break;
        case 1: /* 90 degree, portrait view */
            src_width = dest_height;
            src_height = dest_width;
            dest_row_pitch = -surface_bytes_per_pixel(ds);
            dest_col_pitch = surface_stride(ds);
            break;
        case 2: /* 180 degree, inverted landscape view */
            src_width = dest_width;
            src_height = dest_height;
            dest_row_pitch = -surface_stride(ds);
            dest_col_pitch = -surface_bytes_per_pixel(ds);
            break;
        case 3: /* 270 degree, mirror portrait view */
            src_width = dest_height;
            src_height = dest_width;
            dest_row_pitch = surface_bytes_per_pixel(ds);
            dest_col_pitch = -surface_stride(ds);
            break;
        default:
            g_assert_not_reached();
        }

        int source_bytes_per_pixel = 2;

        switch (s->format) { /* source format */
        case HAL_PIXEL_FORMAT_RGB_565:
            source_bytes_per_pixel = 2;
            switch (surface_bits_per_pixel(ds)) { /* dest format */
            case 8:  fn = draw_line_16_8;  break;
            case 15: fn = draw_line_16_15; break;
            case 16: fn = draw_line_16_16; break;
            case 24: fn = draw_line_16_24; break;
            case 32: fn = draw_line_16_32; break;
            default:
                hw_error("goldfish_fb: bad dest color depth\n");
                return;
            }
            break;
        case HAL_PIXEL_FORMAT_RGBX_8888:
            source_bytes_per_pixel = 4;
            switch (surface_bits_per_pixel(ds)) { /* dest format */
            case 8:  fn = draw_line_32_8;  break;
            case 15: fn = draw_line_32_15; break;
            case 16: fn = draw_line_32_16; break;
            case 24: fn = draw_line_32_24; break;
            case 32: fn = draw_line_32_32; break;
            default:
                hw_error("goldfish_fb: bad dest color depth\n");
                return;
            }
            break;
        default:
            hw_error("goldfish_fb: bad source color format\n");
            return;
        }

        ymin = 0;
        framebuffer_update_display(ds, address_space, s->fb_base,
                                   src_width, src_height,
                                   src_width * source_bytes_per_pixel,
                                   dest_row_pitch, dest_col_pitch,
                                   full_update,
                                   fn, ds, &ymin, &ymax);
    }

    ymax += 1;
    if (ymin >= 0) {
        if (s->rotation % 2) {
            /* In portrait mode we are drawing "sideways" so always
             * need to update the whole screen */
            trace_goldfish_fb_update_display(0, dest_height, 0, dest_width);
            dpy_gfx_update(s->con, 0, 0, dest_width, dest_height);

        } else {
            trace_goldfish_fb_update_display(ymin, ymax-ymin, 0, dest_width);
            dpy_gfx_update(s->con, 0, ymin, dest_width, ymax-ymin);
        }
    }
}
static uint64_t goldfish_fb_read(void *opaque, hwaddr offset, unsigned size)
{
    uint64_t ret = 0;
    struct goldfish_fb_state *s = opaque;
    DisplaySurface *ds = qemu_console_surface(s->con);

#ifndef USE_ANDROID_EMU
    int android_display_bpp = surface_bits_per_pixel(ds);
#endif

    switch(offset) {
        case FB_GET_WIDTH:
            ret = surface_width(ds);
            break;

        case FB_GET_HEIGHT:
            ret = surface_height(ds);
            break;

        case FB_INT_STATUS:
            ret = s->int_status & s->int_enable;
            if(ret) {
                s->int_status &= ~ret;
                qemu_irq_lower(s->irq);
            }
            break;

        case FB_GET_PHYS_WIDTH:
            ret = pixels_to_mm( surface_width(ds), s->dpi );
            break;

        case FB_GET_PHYS_HEIGHT:
            ret = pixels_to_mm( surface_height(ds), s->dpi );
            break;

        case FB_GET_FORMAT:
            /* A kernel making this query supports high color and true color */
            switch (android_display_bpp) {   /* hw.lcd.depth */
            case 32:
            case 24:
               ret = HAL_PIXEL_FORMAT_RGBX_8888;
               break;
            case 16:
               ret = HAL_PIXEL_FORMAT_RGB_565;
               break;
            default:
               error_report("goldfish_fb_read: Bad android_display_bpp %d",
                       android_display_bpp);
               break;
            }
            s->format = ret;
            break;

        default:
            error_report("goldfish_fb_read: Bad offset 0x" TARGET_FMT_plx,
                    offset);
            break;
    }

    trace_goldfish_fb_memory_read(offset, ret);
    return ret;
}
Пример #28
0
/*
 * Send a mouse event from the client to the guest OS
 *
 * The QEMU mouse can be in either relative, or absolute mode.
 * Movement is sent separately from button state, which has to
 * be encoded as virtual key events. We also don't actually get
 * given any button up/down events, so have to track changes in
 * the button state.
 */
static void xenfb_mouse_event(DeviceState *dev, QemuConsole *src,
                              InputEvent *evt)
{
    struct XenInput *xenfb = (struct XenInput *)dev;
    InputBtnEvent *btn;
    InputMoveEvent *move;
    QemuConsole *con;
    DisplaySurface *surface;
    int scale;

    switch (evt->type) {
    case INPUT_EVENT_KIND_BTN:
        btn = evt->u.btn.data;
        switch (btn->button) {
        case INPUT_BUTTON_LEFT:
            xenfb_send_key(xenfb, btn->down, BTN_LEFT);
            break;
        case INPUT_BUTTON_RIGHT:
            xenfb_send_key(xenfb, btn->down, BTN_LEFT + 1);
            break;
        case INPUT_BUTTON_MIDDLE:
            xenfb_send_key(xenfb, btn->down, BTN_LEFT + 2);
            break;
        case INPUT_BUTTON_WHEEL_UP:
            if (btn->down) {
                xenfb->wheel--;
            }
            break;
        case INPUT_BUTTON_WHEEL_DOWN:
            if (btn->down) {
                xenfb->wheel++;
            }
            break;
        default:
            break;
        }
        break;

    case INPUT_EVENT_KIND_ABS:
        move = evt->u.abs.data;
        if (xenfb->raw_pointer_wanted) {
            xenfb->axis[move->axis] = move->value;
        } else {
            con = qemu_console_lookup_by_index(0);
            if (!con) {
                xen_pv_printf(&xenfb->c.xendev, 0, "No QEMU console available");
                return;
            }
            surface = qemu_console_surface(con);
            switch (move->axis) {
            case INPUT_AXIS_X:
                scale = surface_width(surface) - 1;
                break;
            case INPUT_AXIS_Y:
                scale = surface_height(surface) - 1;
                break;
            default:
                scale = 0x8000;
                break;
            }
            xenfb->axis[move->axis] = move->value * scale / 0x7fff;
        }
        break;

    case INPUT_EVENT_KIND_REL:
        move = evt->u.rel.data;
        xenfb->axis[move->axis] += move->value;
        break;

    default:
        break;
    }
}
Пример #29
0
static void handle_keydown(SDL_Event *ev)
{
    int mod_state;
    int keycode;

    if (alt_grab) {
        mod_state = (SDL_GetModState() & (gui_grab_code | KMOD_LSHIFT)) ==
                    (gui_grab_code | KMOD_LSHIFT);
    } else if (ctrl_grab) {
        mod_state = (SDL_GetModState() & KMOD_RCTRL) == KMOD_RCTRL;
    } else {
        mod_state = (SDL_GetModState() & gui_grab_code) == gui_grab_code;
    }
    gui_key_modifier_pressed = mod_state;

    if (gui_key_modifier_pressed) {
        keycode = sdl_keyevent_to_keycode(&ev->key);
        switch (keycode) {
        case 0x21: /* 'f' key on US keyboard */
            toggle_full_screen();
            gui_keysym = 1;
            break;
        case 0x16: /* 'u' key on US keyboard */
            if (scaling_active) {
                scaling_active = 0;
                sdl_switch(dcl, NULL);
                graphic_hw_invalidate(NULL);
                graphic_hw_update(NULL);
            }
            gui_keysym = 1;
            break;
        case 0x02 ... 0x0a: /* '1' to '9' keys */
            /* Reset the modifiers sent to the current console */
            reset_keys();
            console_select(keycode - 0x02);
            gui_keysym = 1;
            if (gui_fullscreen) {
                break;
            }
            if (!qemu_console_is_graphic(NULL)) {
                /* release grab if going to a text console */
                if (gui_grab) {
                    sdl_grab_end();
                } else if (absolute_enabled) {
                    sdl_show_cursor();
                }
            } else if (absolute_enabled) {
                sdl_hide_cursor();
                absolute_mouse_grab();
            }
            break;
        case 0x1b: /* '+' */
        case 0x35: /* '-' */
            if (!gui_fullscreen) {
                int width = MAX(real_screen->w + (keycode == 0x1b ? 50 : -50),
                                160);
                int height = (surface_height(surface) * width) /
                    surface_width(surface);

                sdl_scale(width, height);
                graphic_hw_invalidate(NULL);
                graphic_hw_update(NULL);
                gui_keysym = 1;
            }
        default:
            break;
        }
    } else if (!qemu_console_is_graphic(NULL)) {