Пример #1
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);
}
Пример #2
0
void surface_gl_update_texture(ConsoleGLState *gls,
                               DisplaySurface *surface,
                               int x, int y, int w, int h)
{
    uint8_t *data = (void *)surface_data(surface);

    assert(gls);

    glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT,
                  surface_stride(surface) / surface_bytes_per_pixel(surface));
    glTexSubImage2D(GL_TEXTURE_2D, 0,
                    x, y, w, h,
                    surface->glformat, surface->gltype,
                    data + surface_stride(surface) * y
                    + surface_bytes_per_pixel(surface) * x);
}
Пример #3
0
static uint32_t vigs_dpy_get_bpp(void *user_data)
{
    VIGSState *s = user_data;
    DisplaySurface *ds = qemu_console_surface(s->con);

    return surface_bytes_per_pixel(ds);
}
Пример #4
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;
                }
            }
        }
    }
Пример #5
0
static void tc6393xb_draw_blank(TC6393xbState *s, int full_update)
{
    DisplaySurface *surface = qemu_console_surface(s->con);
    int i, w;
    uint8_t *d;

    if (!full_update)
        return;

    w = s->scr_width * surface_bytes_per_pixel(surface);
    d = surface_data(surface);
    for(i = 0; i < s->scr_height; i++) {
        memset(d, 0, w);
        d += surface_stride(surface);
    }

    dpy_gfx_update(s->con, 0, 0, s->scr_width, s->scr_height);
}
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);
        }
    }
}