Exemple #1
0
static void sdl_resize(DisplayState *ds)
{
    if (!scaling_active) {
        do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0);
    } else if (real_screen->format->BitsPerPixel != ds_get_bits_per_pixel(ds)) {
        do_sdl_resize(real_screen->w, real_screen->h,
                      ds_get_bits_per_pixel(ds));
    }
    sdl_setdata(ds);
}
Exemple #2
0
static void sdl_resize(DisplayState *ds)
{
    if  (!allocator) {
        if (!scaling_active)
            do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0);
        else if (real_screen->format->BitsPerPixel != ds_get_bits_per_pixel(ds))
            do_sdl_resize(real_screen->w, real_screen->h, ds_get_bits_per_pixel(ds));
        sdl_setdata(ds);
    } else {
        if (guest_screen != NULL) {
            SDL_FreeSurface(guest_screen);
            guest_screen = NULL;
        }
    }
}
Exemple #3
0
static void g364fb_draw_graphic8(G364State *s)
{
    int i, w;
    uint8_t *vram;
    uint8_t *data_display, *dd;
    ram_addr_t page, page_min, page_max;
    int x, y;
    int xmin, xmax;
    int ymin, ymax;
    int xcursor, ycursor;
    unsigned int (*rgb_to_pixel)(unsigned int r, unsigned int g, unsigned int b);

    switch (ds_get_bits_per_pixel(s->ds)) {
        case 8:
            rgb_to_pixel = rgb_to_pixel8;
            w = 1;
            break;
        case 15:
            rgb_to_pixel = rgb_to_pixel15;
            w = 2;
            break;
        case 16:
            rgb_to_pixel = rgb_to_pixel16;
            w = 2;
            break;
        case 32:
            rgb_to_pixel = rgb_to_pixel32;
            w = 4;
            break;
        default:
            BADF("unknown host depth %d\n", ds_get_bits_per_pixel(s->ds));
            return;
    }

    page = s->vram_offset;
    page_min = (ram_addr_t)-1;
    page_max = 0;

    x = y = 0;
    xmin = s->width;
    xmax = 0;
    ymin = s->height;
    ymax = 0;

    if (!(s->ctla & CTLA_NO_CURSOR)) {
        xcursor = s->cursor_position >> 12;
        ycursor = s->cursor_position & 0xfff;
    } else {
Exemple #4
0
Fichier : tcx.c Projet : asias/qemu
static void update_palette_entries(TCXState *s, int start, int end)
{
    int i;
    for(i = start; i < end; i++) {
        switch(ds_get_bits_per_pixel(s->ds)) {
        default:
        case 8:
            s->palette[i] = rgb_to_pixel8(s->r[i], s->g[i], s->b[i]);
            break;
        case 15:
            s->palette[i] = rgb_to_pixel15(s->r[i], s->g[i], s->b[i]);
            break;
        case 16:
            s->palette[i] = rgb_to_pixel16(s->r[i], s->g[i], s->b[i]);
            break;
        case 32:
            if (is_surface_bgr(s->ds->surface))
                s->palette[i] = rgb_to_pixel32bgr(s->r[i], s->g[i], s->b[i]);
            else
                s->palette[i] = rgb_to_pixel32(s->r[i], s->g[i], s->b[i]);
            break;
        }
    }
    if (s->depth == 24) {
        tcx24_set_dirty(s);
    } else {
        tcx_set_dirty(s);
    }
}
Exemple #5
0
static void toggle_full_screen(DisplayState *ds)
{
    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(ds_get_width(ds), ds_get_height(ds),
                      ds_get_bits_per_pixel(ds));
        scaling_active = 0;

        gui_saved_grab = gui_grab;
        sdl_grab_start();
    } else {
        if (gui_saved_scaling) {
            sdl_scale(ds, gui_saved_width, gui_saved_height);
        } else {
            do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0);
        }
        if (!gui_saved_grab || !is_graphic_console()) {
            sdl_grab_end();
        }
    }
    vga_hw_invalidate();
    vga_hw_update();
}
Exemple #6
0
static void pl110_update_pallette(pl110_state *s, int n)
{
    int i;
    uint32_t raw;
    unsigned int r, g, b;

    raw = s->raw_pallette[n];
    n <<= 1;
    for (i = 0; i < 2; i++) {
        r = (raw & 0x1f) << 3;
        raw >>= 5;
        g = (raw & 0x1f) << 3;
        raw >>= 5;
        b = (raw & 0x1f) << 3;
        /* The I bit is ignored.  */
        raw >>= 6;
        switch (ds_get_bits_per_pixel(s->ds)) {
        case 8:
            s->pallette[n] = rgb_to_pixel8(r, g, b);
            break;
        case 15:
            s->pallette[n] = rgb_to_pixel15(r, g, b);
            break;
        case 16:
            s->pallette[n] = rgb_to_pixel16(r, g, b);
            break;
        case 24:
        case 32:
            s->pallette[n] = rgb_to_pixel32(r, g, b);
            break;
        }
        n++;
    }
}
Exemple #7
0
PXA2xxLCDState *pxa2xx_lcdc_init(target_phys_addr_t base, qemu_irq irq)
{
    int iomemtype;
    PXA2xxLCDState *s;

    s = (PXA2xxLCDState *) qemu_mallocz(sizeof(PXA2xxLCDState));
    s->invalidated = 1;
    s->irq = irq;

    pxa2xx_lcdc_orientation(s, graphic_rotate);

    iomemtype = cpu_register_io_memory(pxa2xx_lcdc_readfn,
                    pxa2xx_lcdc_writefn, s);
    cpu_register_physical_memory(base, 0x00100000, iomemtype);

    s->ds = graphic_console_init(pxa2xx_update_display,
                                 pxa2xx_invalidate_display,
                                 pxa2xx_screen_dump, NULL, s);

    switch (ds_get_bits_per_pixel(s->ds)) {
    case 0:
        s->dest_width = 0;
        break;
    case 8:
        s->line_fn[0] = pxa2xx_draw_fn_8;
        s->line_fn[1] = pxa2xx_draw_fn_8t;
        s->dest_width = 1;
        break;
    case 15:
        s->line_fn[0] = pxa2xx_draw_fn_15;
        s->line_fn[1] = pxa2xx_draw_fn_15t;
        s->dest_width = 2;
        break;
    case 16:
        s->line_fn[0] = pxa2xx_draw_fn_16;
        s->line_fn[1] = pxa2xx_draw_fn_16t;
        s->dest_width = 2;
        break;
    case 24:
        s->line_fn[0] = pxa2xx_draw_fn_24;
        s->line_fn[1] = pxa2xx_draw_fn_24t;
        s->dest_width = 3;
        break;
    case 32:
        s->line_fn[0] = pxa2xx_draw_fn_32;
        s->line_fn[1] = pxa2xx_draw_fn_32t;
        s->dest_width = 4;
        break;
    default:
        fprintf(stderr, "%s: Bad color depth\n", __FUNCTION__);
        exit(1);
    }

    register_savevm("pxa2xx_lcdc", 0, 0,
                    pxa2xx_lcdc_save, pxa2xx_lcdc_load, s);

    return s;
}
Exemple #8
0
static void vgafb_update_display(void *opaque)
{
    MilkymistVgafbState *s = opaque;
    int first = 0;
    int last = 0;
    drawfn fn;

    if (!vgafb_enabled(s)) {
        return;
    }

    int dest_width = s->regs[R_HRES];

    switch (ds_get_bits_per_pixel(s->ds)) {
    case 0:
        return;
    case 8:
        fn = draw_line_8;
        break;
    case 15:
        fn = draw_line_15;
        dest_width *= 2;
        break;
    case 16:
        fn = draw_line_16;
        dest_width *= 2;
        break;
    case 24:
        fn = draw_line_24;
        dest_width *= 3;
        break;
    case 32:
        fn = draw_line_32;
        dest_width *= 4;
        break;
    default:
        hw_error("milkymist_vgafb: bad color depth\n");
        break;
    }

    framebuffer_update_display(s->ds,
                               s->regs[R_BASEADDRESS] + s->fb_offset,
                               s->regs[R_HRES],
                               s->regs[R_VRES],
                               s->regs[R_HRES] * 2,
                               dest_width,
                               0,
                               s->invalidate,
                               fn,
                               NULL,
                               &first, &last);

    if (first >= 0) {
        dpy_update(s->ds, 0, first, s->regs[R_HRES], last - first + 1);
    }
    s->invalidate = 0;
}
Exemple #9
0
static void sdl_setdata(DisplayState *ds)
{
    if (guest_screen != NULL) SDL_FreeSurface(guest_screen);

    guest_screen = SDL_CreateRGBSurfaceFrom(ds_get_data(ds), ds_get_width(ds), ds_get_height(ds),
                                            ds_get_bits_per_pixel(ds), ds_get_linesize(ds),
                                            ds->surface->pf.rmask, ds->surface->pf.gmask,
                                            ds->surface->pf.bmask, ds->surface->pf.amask);
}
Exemple #10
0
Fichier : sdl.c Projet : CPFL/gxen
static void opengl_setdata(DisplayState *ds)
{
    glEnable(GL_TEXTURE_RECTANGLE_ARB);
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    glClearColor(0, 0, 0, 0);
    glDisable(GL_BLEND);
    glDisable(GL_LIGHTING);
    glDisable(GL_DEPTH_TEST);
    glDepthMask(GL_FALSE);
    glDisable(GL_CULL_FACE);
    glViewport( 0, 0, real_screen->w, real_screen->h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, real_screen->w, real_screen->h, 0, -1,1);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glClear(GL_COLOR_BUFFER_BIT);

    if (texture_ref) {
        glDeleteTextures(1, &texture_ref);
        texture_ref = 0;
    }

    glGenTextures(1, &texture_ref);
    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_ref);
    glPixelStorei(GL_UNPACK_LSB_FIRST, 1);
    switch (ds_get_bits_per_pixel(ds)) {
        case 16:
            tex_format = GL_RGB;
            tex_type = GL_UNSIGNED_SHORT_5_6_5;
            break;
        case 24:
            tex_format = GL_BGR;
            tex_type = GL_UNSIGNED_BYTE;
            break;
        case 32:
            if (bgr == (ds->surface->pf.rshift < ds->surface->pf.bshift)) {
                tex_format = GL_BGRA;
                tex_type = GL_UNSIGNED_BYTE;
            } else {
                tex_format = GL_RGBA;
                tex_type = GL_UNSIGNED_BYTE;                
            }
            break;
    }   
    glPixelStorei(GL_UNPACK_ROW_LENGTH, (ds_get_linesize(ds) / ds_get_bytes_per_pixel(ds)));
    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, gl_format, ds_get_width(ds), ds_get_height(ds), 0, tex_format, tex_type, ds_get_data(ds));
    glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_PRIORITY, 1.0);
    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
}
/*
 * This copies data from the guest framebuffer region, into QEMU's
 * displaysurface. qemu uses 16 or 32 bpp.  In case the pv framebuffer
 * uses something else we must convert and copy, otherwise we can
 * supply the buffer directly and no thing here.
 */
static void xenfb_guest_copy(struct XenFB *xenfb, int x, int y, int w, int h)
{
    int line, oops = 0;
    int bpp = ds_get_bits_per_pixel(xenfb->c.ds);
    int linesize = ds_get_linesize(xenfb->c.ds);
    uint8_t *data = ds_get_data(xenfb->c.ds);

    if (!is_buffer_shared(xenfb->c.ds->surface)) {
        switch (xenfb->depth) {
        case 8:
            if (bpp == 16) {
                BLT(uint8_t, uint16_t,   3, 3, 2,   5, 6, 5);
            } else if (bpp == 32) {
                BLT(uint8_t, uint32_t,   3, 3, 2,   8, 8, 8);
            } else {
                oops = 1;
            }
            break;
        case 24:
            if (bpp == 16) {
                BLT(uint32_t, uint16_t,  8, 8, 8,   5, 6, 5);
            } else if (bpp == 32) {
                BLT(uint32_t, uint32_t,  8, 8, 8,   8, 8, 8);
            } else {
                oops = 1;
            }
            break;
        default:
            oops = 1;
	}
    }
    if (oops) /* should not happen */
        xen_be_printf(&xenfb->c.xendev, 0, "%s: oops: convert %d -> %d bpp?\n",
                      __FUNCTION__, xenfb->depth, bpp);

    dpy_update(xenfb->c.ds, x, y, w, h);
}
Exemple #12
0
Fichier : tcx.c Projet : asias/qemu
static void tcx24_update_display(void *opaque)
{
    TCXState *ts = opaque;
    ram_addr_t page, page_min, page_max, cpage, page24;
    int y, y_start, dd, ds;
    uint8_t *d, *s;
    uint32_t *cptr, *s24;

    if (ds_get_bits_per_pixel(ts->ds) != 32)
            return;
    page = 0;
    page24 = ts->vram24_offset;
    cpage = ts->cplane_offset;
    y_start = -1;
    page_min = -1;
    page_max = 0;
    d = ds_get_data(ts->ds);
    s = ts->vram;
    s24 = ts->vram24;
    cptr = ts->cplane;
    dd = ds_get_linesize(ts->ds);
    ds = 1024;

    for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE,
            page24 += TARGET_PAGE_SIZE, cpage += TARGET_PAGE_SIZE) {
        if (check_dirty(ts, page, page24, cpage)) {
            if (y_start < 0)
                y_start = y;
            if (page < page_min)
                page_min = page;
            if (page > page_max)
                page_max = page;
            tcx24_draw_line32(ts, d, s, ts->width, cptr, s24);
            d += dd;
            s += ds;
            cptr += ds;
            s24 += ds;
            tcx24_draw_line32(ts, d, s, ts->width, cptr, s24);
            d += dd;
            s += ds;
            cptr += ds;
            s24 += ds;
            tcx24_draw_line32(ts, d, s, ts->width, cptr, s24);
            d += dd;
            s += ds;
            cptr += ds;
            s24 += ds;
            tcx24_draw_line32(ts, d, s, ts->width, cptr, s24);
            d += dd;
            s += ds;
            cptr += ds;
            s24 += ds;
        } else {
            if (y_start >= 0) {
                /* flush to display */
                dpy_update(ts->ds, 0, y_start,
                           ts->width, y - y_start);
                y_start = -1;
            }
            d += dd * 4;
            s += ds * 4;
            cptr += ds * 4;
            s24 += ds * 4;
        }
    }
    if (y_start >= 0) {
        /* flush to display */
        dpy_update(ts->ds, 0, y_start,
                   ts->width, y - y_start);
    }
    /* reset modified pages */
    if (page_max >= page_min) {
        reset_dirty(ts, page_min, page_max, page24, cpage);
    }
}
Exemple #13
0
Fichier : tcx.c Projet : asias/qemu
/* Fixed line length 1024 allows us to do nice tricks not possible on
   VGA... */
static void tcx_update_display(void *opaque)
{
    TCXState *ts = opaque;
    ram_addr_t page, page_min, page_max;
    int y, y_start, dd, ds;
    uint8_t *d, *s;
    void (*f)(TCXState *s1, uint8_t *dst, const uint8_t *src, int width);

    if (ds_get_bits_per_pixel(ts->ds) == 0)
        return;
    page = 0;
    y_start = -1;
    page_min = -1;
    page_max = 0;
    d = ds_get_data(ts->ds);
    s = ts->vram;
    dd = ds_get_linesize(ts->ds);
    ds = 1024;

    switch (ds_get_bits_per_pixel(ts->ds)) {
    case 32:
        f = tcx_draw_line32;
        break;
    case 15:
    case 16:
        f = tcx_draw_line16;
        break;
    default:
    case 8:
        f = tcx_draw_line8;
        break;
    case 0:
        return;
    }

    for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE) {
        if (memory_region_get_dirty(&ts->vram_mem, page, TARGET_PAGE_SIZE,
                                    DIRTY_MEMORY_VGA)) {
            if (y_start < 0)
                y_start = y;
            if (page < page_min)
                page_min = page;
            if (page > page_max)
                page_max = page;
            f(ts, d, s, ts->width);
            d += dd;
            s += ds;
            f(ts, d, s, ts->width);
            d += dd;
            s += ds;
            f(ts, d, s, ts->width);
            d += dd;
            s += ds;
            f(ts, d, s, ts->width);
            d += dd;
            s += ds;
        } else {
            if (y_start >= 0) {
                /* flush to display */
                dpy_update(ts->ds, 0, y_start,
                           ts->width, y - y_start);
                y_start = -1;
            }
            d += dd * 4;
            s += ds * 4;
        }
    }
    if (y_start >= 0) {
        /* flush to display */
        dpy_update(ts->ds, 0, y_start,
                   ts->width, y - y_start);
    }
    /* reset modified pages */
    if (page_max >= page_min) {
        memory_region_reset_dirty(&ts->vram_mem,
                                  page_min, page_max + TARGET_PAGE_SIZE,
                                  DIRTY_MEMORY_VGA);
    }
}
Exemple #14
0
static void pl110_update_display(void *opaque)
{
    pl110_state *s = (pl110_state *)opaque;
    drawfn* fntable;
    drawfn fn;
    int dest_width;
    int src_width;
    int bpp_offset;
    int first;
    int last;

    if (!pl110_enabled(s))
        return;

    switch (ds_get_bits_per_pixel(s->ds)) {
    case 0:
        return;
    case 8:
        fntable = pl110_draw_fn_8;
        dest_width = 1;
        break;
    case 15:
        fntable = pl110_draw_fn_15;
        dest_width = 2;
        break;
    case 16:
        fntable = pl110_draw_fn_16;
        dest_width = 2;
        break;
    case 24:
        fntable = pl110_draw_fn_24;
        dest_width = 3;
        break;
    case 32:
        fntable = pl110_draw_fn_32;
        dest_width = 4;
        break;
    default:
        fprintf(stderr, "pl110: Bad color depth\n");
        exit(1);
    }
    if (s->cr & PL110_CR_BGR)
        bpp_offset = 0;
    else
        bpp_offset = 18;

    if (s->cr & PL110_CR_BEBO)
        fn = fntable[s->bpp + 6 + bpp_offset];
    else if (s->cr & PL110_CR_BEPO)
        fn = fntable[s->bpp + 12 + bpp_offset];
    else
        fn = fntable[s->bpp + bpp_offset];

    src_width = s->cols;
    switch (s->bpp) {
    case BPP_1:
        src_width >>= 3;
        break;
    case BPP_2:
        src_width >>= 2;
        break;
    case BPP_4:
        src_width >>= 1;
        break;
    case BPP_8:
        break;
    case BPP_16:
        src_width <<= 1;
        break;
    case BPP_32:
        src_width <<= 2;
        break;
    }
    dest_width *= s->cols;
    first = 0;
    framebuffer_update_display(s->ds,
                               s->upbase, s->cols, s->rows,
                               src_width, dest_width, 0,
                               s->invalidate,
                               fn, s->pallette,
                               &first, &last);
    if (first >= 0) {
        dpy_update(s->ds, 0, first, s->cols, last - first + 1);
    }
    s->invalidate = 0;
}
Exemple #15
0
static void bcm2708_fb_update(void *_opaque)
{
	struct bcm2708_vc *vc = _opaque;
    drawfn* fntable;
    drawfn fn;
    int dest_width;
    int src_width;
    int bpp_offset;
    int first;
    int last;

    switch (ds_get_bits_per_pixel(vc->disp))
	{
    case 0:
        return;
    case 8:
        fntable = pl110_draw_fn_8;
        dest_width = 1;
        break;
    case 15:
        fntable = pl110_draw_fn_15;
        dest_width = 2;
        break;
    case 16:
        fntable = pl110_draw_fn_16;
        dest_width = 2;
        break;
    case 24:
        fntable = pl110_draw_fn_24;
        dest_width = 3;
        break;
    case 32:
        fntable = pl110_draw_fn_32;
        dest_width = 4;
        break;
    default:
        fprintf(stderr, "bcm2708: Bad color depth\n");
        exit(1);
    }

    bpp_offset = 0;
    fn = fntable[vc->fb_bpp + bpp_offset];

    src_width = vc->fb.xres;
    switch (vc->fb_bpp) {
    case BPP_1:
        src_width >>= 3;
        break;
    case BPP_2:
        src_width >>= 2;
        break;
    case BPP_4:
        src_width >>= 1;
        break;
    case BPP_8:
        break;
    case BPP_16:
    case BPP_16_565:
    case BPP_12:
        src_width <<= 1;
        break;
    case BPP_32:
        src_width <<= 2;
        break;
    }

    dest_width *= vc->fb.xres;
    first = 0;

	framebuffer_update_display(vc->disp, get_system_memory(),
			vc->fb.base, vc->fb.xres, vc->fb.yres,
			src_width, dest_width, 0,
			vc->fb_invalidate,
			fn, NULL,
			&first, &last);
	if (first >= 0) {
		dpy_update(vc->disp, 0, first, vc->fb.xres, last - first + 1);
	}

    vc->fb_invalidate = 0;
}
Exemple #16
0
/* Load new palette for a given DMA channel, convert to internal format */
static void pxa2xx_palette_parse(PXA2xxLCDState *s, int ch, int bpp)
{
    int i, n, format, r, g, b, alpha;
    uint32_t *dest;
    uint8_t *src;
    s->pal_for = LCCR4_PALFOR(s->control[4]);
    format = s->pal_for;

    switch (bpp) {
    case pxa_lcdc_2bpp:
        n = 4;
        break;
    case pxa_lcdc_4bpp:
        n = 16;
        break;
    case pxa_lcdc_8bpp:
        n = 256;
        break;
    default:
        format = 0;
        return;
    }

    src = (uint8_t *) s->dma_ch[ch].pbuffer;
    dest = (uint32_t *) s->dma_ch[ch].palette;
    alpha = r = g = b = 0;

    for (i = 0; i < n; i ++) {
        switch (format) {
        case 0: /* 16 bpp, no transparency */
            alpha = 0;
            if (s->control[0] & LCCR0_CMS) {
                r = g = b = *(uint16_t *) src & 0xff;
            }
            else {
                r = (*(uint16_t *) src & 0xf800) >> 8;
                g = (*(uint16_t *) src & 0x07e0) >> 3;
                b = (*(uint16_t *) src & 0x001f) << 3;
            }
            src += 2;
            break;
        case 1: /* 16 bpp plus transparency */
            alpha = *(uint16_t *) src & (1 << 24);
            if (s->control[0] & LCCR0_CMS)
                r = g = b = *(uint16_t *) src & 0xff;
            else {
                r = (*(uint16_t *) src & 0xf800) >> 8;
                g = (*(uint16_t *) src & 0x07e0) >> 3;
                b = (*(uint16_t *) src & 0x001f) << 3;
            }
            src += 2;
            break;
        case 2: /* 18 bpp plus transparency */
            alpha = *(uint32_t *) src & (1 << 24);
            if (s->control[0] & LCCR0_CMS)
                r = g = b = *(uint32_t *) src & 0xff;
            else {
                r = (*(uint32_t *) src & 0xf80000) >> 16;
                g = (*(uint32_t *) src & 0x00fc00) >> 8;
                b = (*(uint32_t *) src & 0x0000f8);
            }
            src += 4;
            break;
        case 3: /* 24 bpp plus transparency */
            alpha = *(uint32_t *) src & (1 << 24);
            if (s->control[0] & LCCR0_CMS)
                r = g = b = *(uint32_t *) src & 0xff;
            else {
                r = (*(uint32_t *) src & 0xff0000) >> 16;
                g = (*(uint32_t *) src & 0x00ff00) >> 8;
                b = (*(uint32_t *) src & 0x0000ff);
            }
            src += 4;
            break;
        }
        switch (ds_get_bits_per_pixel(s->ds)) {
        case 8:
            *dest = rgb_to_pixel8(r, g, b) | alpha;
            break;
        case 15:
            *dest = rgb_to_pixel15(r, g, b) | alpha;
            break;
        case 16:
            *dest = rgb_to_pixel16(r, g, b) | alpha;
            break;
        case 24:
            *dest = rgb_to_pixel24(r, g, b) | alpha;
            break;
        case 32:
            *dest = rgb_to_pixel32(r, g, b) | alpha;
            break;
        }
        dest ++;
    }
}