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); }
static void tc6393xb_draw_graphic(TC6393xbState *s, int full_update) { DisplaySurface *surface = qemu_console_surface(s->con); switch (surface_bits_per_pixel(surface)) { case 8: tc6393xb_draw_graphic8(s); break; case 15: tc6393xb_draw_graphic15(s); break; case 16: tc6393xb_draw_graphic16(s); break; case 24: tc6393xb_draw_graphic24(s); break; case 32: tc6393xb_draw_graphic32(s); break; default: printf("tc6393xb: unknown depth %d\n", surface_bits_per_pixel(surface)); return; } dpy_gfx_update(s->con, 0, 0, s->scr_width, s->scr_height); }
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); } }
static void vgafb_update_display(void *opaque) { MilkymistVgafbState *s = opaque; DisplaySurface *surface = qemu_console_surface(s->con); int first = 0; int last = 0; drawfn fn; if (!vgafb_enabled(s)) { return; } int dest_width = s->regs[R_HRES]; switch (surface_bits_per_pixel(surface)) { 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(surface, sysbus_address_space(&s->busdev), 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_gfx_update(s->con, 0, first, s->regs[R_HRES], last - first + 1); } s->invalidate = 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 qxl_render_update_area_unlocked(PCIQXLDevice *qxl) { VGACommonState *vga = &qxl->vga; DisplaySurface *surface; int i; if (qxl->guest_primary.resized) { qxl->guest_primary.resized = 0; qxl->guest_primary.data = memory_region_get_ram_ptr(&qxl->vga.vram); qxl_set_rect_to_surface(qxl, &qxl->dirty[0]); qxl->num_dirty_rects = 1; trace_qxl_render_guest_primary_resized( qxl->guest_primary.surface.width, qxl->guest_primary.surface.height, qxl->guest_primary.qxl_stride, qxl->guest_primary.bytes_pp, qxl->guest_primary.bits_pp); if (qxl->guest_primary.qxl_stride > 0) { surface = qemu_create_displaysurface_from (qxl->guest_primary.surface.width, qxl->guest_primary.surface.height, qxl->guest_primary.bits_pp, qxl->guest_primary.abs_stride, qxl->guest_primary.data, false); } else { surface = qemu_create_displaysurface (qxl->guest_primary.surface.width, qxl->guest_primary.surface.height); } dpy_gfx_replace_surface(vga->con, surface); } for (i = 0; i < qxl->num_dirty_rects; i++) { if (qemu_spice_rect_is_empty(qxl->dirty+i)) { break; } qxl_blit(qxl, qxl->dirty+i); dpy_gfx_update(vga->con, qxl->dirty[i].left, qxl->dirty[i].top, qxl->dirty[i].right - qxl->dirty[i].left, qxl->dirty[i].bottom - qxl->dirty[i].top); } qxl->num_dirty_rects = 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) { DisplaySurface *surface = qemu_console_surface(xenfb->c.con); int line, oops = 0; int bpp = surface_bits_per_pixel(surface); int linesize = surface_stride(surface); uint8_t *data = surface_data(surface); if (!is_buffer_shared(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_gfx_update(xenfb->c.con, x, y, w, h); }
static void cg3_update_display(void *opaque) { CG3State *s = opaque; DisplaySurface *surface = qemu_console_surface(s->con); const uint8_t *pix; uint32_t *data; uint32_t dval; int x, y, y_start; unsigned int width, height; ram_addr_t page, page_min, page_max; if (surface_bits_per_pixel(surface) != 32) { return; } width = s->width; height = s->height; y_start = -1; page_min = -1; page_max = 0; page = 0; pix = memory_region_get_ram_ptr(&s->vram_mem); data = (uint32_t *)surface_data(surface); for (y = 0; y < height; y++) { int update = s->full_update; page = (y * width) & TARGET_PAGE_MASK; update |= memory_region_get_dirty(&s->vram_mem, page, page + width, DIRTY_MEMORY_VGA); if (update) { if (y_start < 0) { y_start = y; } if (page < page_min) { page_min = page; } if (page > page_max) { page_max = page; } for (x = 0; x < width; x++) { dval = *pix++; dval = (s->r[dval] << 16) | (s->g[dval] << 8) | s->b[dval]; *data++ = dval; } } else { if (y_start >= 0) { dpy_gfx_update(s->con, 0, y_start, s->width, y - y_start); y_start = -1; } pix += width; data += width; } } s->full_update = 0; if (y_start >= 0) { dpy_gfx_update(s->con, 0, y_start, s->width, y - y_start); } if (page_max >= page_min) { memory_region_reset_dirty(&s->vram_mem, page_min, page_max - page_min + TARGET_PAGE_SIZE, DIRTY_MEMORY_VGA); } /* vsync interrupt? */ if (s->regs[0] & CG3_CR_ENABLE_INTS) { s->regs[1] |= CG3_SR_PENDING_INT; qemu_irq_raise(s->irq); } }
static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl) { VGACommonState *vga = &qxl->vga; DisplaySurface *surface; int i; if (qxl->guest_primary.resized) { qxl->guest_primary.resized = 0; qxl->guest_primary.data = qxl_phys2virt(qxl, qxl->guest_primary.surface.mem, MEMSLOT_GROUP_GUEST); if (!qxl->guest_primary.data) { return; } qxl_set_rect_to_surface(qxl, &qxl->dirty[0]); qxl->num_dirty_rects = 1; trace_qxl_render_guest_primary_resized( qxl->guest_primary.surface.width, qxl->guest_primary.surface.height, qxl->guest_primary.qxl_stride, qxl->guest_primary.bytes_pp, qxl->guest_primary.bits_pp); if (qxl->guest_primary.qxl_stride > 0) { pixman_format_code_t format = qemu_default_pixman_format(qxl->guest_primary.bits_pp, true); surface = qemu_create_displaysurface_from (qxl->guest_primary.surface.width, qxl->guest_primary.surface.height, format, qxl->guest_primary.abs_stride, qxl->guest_primary.data); } else { surface = qemu_create_displaysurface (qxl->guest_primary.surface.width, qxl->guest_primary.surface.height); } dpy_gfx_replace_surface(vga->con, surface); } if (!qxl->guest_primary.data) { return; } for (i = 0; i < qxl->num_dirty_rects; i++) { if (qemu_spice_rect_is_empty(qxl->dirty+i)) { break; } if (qxl->dirty[i].left < 0 || qxl->dirty[i].top < 0 || qxl->dirty[i].left > qxl->dirty[i].right || qxl->dirty[i].top > qxl->dirty[i].bottom || qxl->dirty[i].right > qxl->guest_primary.surface.width || qxl->dirty[i].bottom > qxl->guest_primary.surface.height) { continue; } qxl_blit(qxl, qxl->dirty+i); dpy_gfx_update(vga->con, qxl->dirty[i].left, qxl->dirty[i].top, qxl->dirty[i].right - qxl->dirty[i].left, qxl->dirty[i].bottom - qxl->dirty[i].top); } qxl->num_dirty_rects = 0; }
static void cg3_update_display(void *opaque) { CG3State *s = opaque; DisplaySurface *surface = qemu_console_surface(s->con); const uint8_t *pix; uint32_t *data; uint32_t dval; int x, y, y_start; unsigned int width, height; ram_addr_t page; DirtyBitmapSnapshot *snap = NULL; if (surface_bits_per_pixel(surface) != 32) { return; } width = s->width; height = s->height; y_start = -1; pix = memory_region_get_ram_ptr(&s->vram_mem); data = (uint32_t *)surface_data(surface); if (!s->full_update) { memory_region_sync_dirty_bitmap(&s->vram_mem); snap = memory_region_snapshot_and_clear_dirty(&s->vram_mem, 0x0, memory_region_size(&s->vram_mem), DIRTY_MEMORY_VGA); } for (y = 0; y < height; y++) { int update; page = (ram_addr_t)y * width; if (s->full_update) { update = 1; } else { update = memory_region_snapshot_get_dirty(&s->vram_mem, snap, page, width); } if (update) { if (y_start < 0) { y_start = y; } for (x = 0; x < width; x++) { dval = *pix++; dval = (s->r[dval] << 16) | (s->g[dval] << 8) | s->b[dval]; *data++ = dval; } } else { if (y_start >= 0) { dpy_gfx_update(s->con, 0, y_start, width, y - y_start); y_start = -1; } pix += width; data += width; } } s->full_update = 0; if (y_start >= 0) { dpy_gfx_update(s->con, 0, y_start, width, y - y_start); } /* vsync interrupt? */ if (s->regs[0] & CG3_CR_ENABLE_INTS) { s->regs[1] |= CG3_SR_PENDING_INT; qemu_irq_raise(s->irq); } g_free(snap); }
static void pxa2xx_update_display(void *opaque) { PXA2xxLCDState *s = (PXA2xxLCDState *) opaque; hwaddr fbptr; int miny, maxy; int ch; if (!(s->control[0] & LCCR0_ENB)) return; pxa2xx_descriptor_load(s); pxa2xx_lcdc_resize(s); miny = s->yres; maxy = 0; s->transp = s->dma_ch[2].up || s->dma_ch[3].up; /* Note: With overlay planes the order depends on LCCR0 bit 25. */ for (ch = 0; ch < PXA_LCDDMA_CHANS; ch ++) if (s->dma_ch[ch].up) { if (!s->dma_ch[ch].source) { pxa2xx_dma_ber_set(s, ch); continue; } fbptr = s->dma_ch[ch].source; if (!((fbptr >= PXA2XX_SDRAM_BASE && fbptr <= PXA2XX_SDRAM_BASE + ram_size) || (fbptr >= PXA2XX_INTERNAL_BASE && fbptr <= PXA2XX_INTERNAL_BASE + PXA2XX_INTERNAL_SIZE))) { pxa2xx_dma_ber_set(s, ch); continue; } if (s->dma_ch[ch].command & LDCMD_PAL) { cpu_physical_memory_read(fbptr, s->dma_ch[ch].pbuffer, MAX(LDCMD_LENGTH(s->dma_ch[ch].command), sizeof(s->dma_ch[ch].pbuffer))); pxa2xx_palette_parse(s, ch, s->bpp); } else { /* Do we need to reparse palette */ if (LCCR4_PALFOR(s->control[4]) != s->pal_for) pxa2xx_palette_parse(s, ch, s->bpp); /* ACK frame start */ pxa2xx_dma_sof_set(s, ch); s->dma_ch[ch].redraw(s, fbptr, &miny, &maxy); s->invalidated = 0; /* ACK frame completed */ pxa2xx_dma_eof_set(s, ch); } } if (s->control[0] & LCCR0_DIS) { /* ACK last frame completed */ s->control[0] &= ~LCCR0_ENB; s->status[0] |= LCSR0_LDD; } if (miny >= 0) { switch (s->orientation) { case 0: dpy_gfx_update(s->con, 0, miny, s->xres, maxy - miny + 1); break; case 90: dpy_gfx_update(s->con, miny, 0, maxy - miny + 1, s->xres); break; case 180: maxy = s->yres - maxy - 1; miny = s->yres - miny - 1; dpy_gfx_update(s->con, 0, maxy, s->xres, miny - maxy + 1); break; case 270: maxy = s->yres - maxy - 1; miny = s->yres - miny - 1; dpy_gfx_update(s->con, maxy, 0, miny - maxy + 1, s->xres); break; } } pxa2xx_lcdc_int_update(s); qemu_irq_raise(s->vsync_cb); }
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 void tcx24_update_display(void *opaque) { TCXState *ts = opaque; DisplaySurface *surface = qemu_console_surface(ts->con); 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 (surface_bits_per_pixel(surface) != 32) { return; } page = 0; page24 = ts->vram24_offset; cpage = ts->cplane_offset; y_start = -1; page_min = -1; page_max = 0; d = surface_data(surface); s = ts->vram; s24 = ts->vram24; cptr = ts->cplane; dd = surface_stride(surface); 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_gfx_update(ts->con, 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_gfx_update(ts->con, 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); } }
/* Fixed line length 1024 allows us to do nice tricks not possible on VGA... */ static void tcx_update_display(void *opaque) { TCXState *ts = opaque; DisplaySurface *surface = qemu_console_surface(ts->con); 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 (surface_bits_per_pixel(surface) == 0) { return; } page = 0; y_start = -1; page_min = -1; page_max = 0; d = surface_data(surface); s = ts->vram; dd = surface_stride(surface); ds = 1024; switch (surface_bits_per_pixel(surface)) { 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_gfx_update(ts->con, 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_gfx_update(ts->con, 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 - page_min) + TARGET_PAGE_SIZE, DIRTY_MEMORY_VGA); } }
static void sm_lcd_update_display(void *arg) { lcd_state *s = arg; uint8_t *d; uint32_t colour_on, colour_off, colour; int x, y, bpp; DisplaySurface *surface = qemu_console_surface(s->con); bpp = surface_bits_per_pixel(surface); d = surface_data(surface); // If vibrate is on, simply jiggle the display if (s->vibrate_on) { if (s->vibrate_offset == 0) { s->vibrate_offset = 2; } int bytes_per_pixel; switch (bpp) { case 8: bytes_per_pixel = 1; break; case 15: case 16: bytes_per_pixel = 2; break; case 32: bytes_per_pixel = 4; break; default: abort(); } int total_bytes = NUM_ROWS * NUM_COLS * bytes_per_pixel - abs(s->vibrate_offset) * bytes_per_pixel; if (s->vibrate_offset > 0) { memmove(d, d + s->vibrate_offset * bytes_per_pixel, total_bytes); } else { memmove(d - s->vibrate_offset * bytes_per_pixel, d, total_bytes); } s->vibrate_offset *= -1; dpy_gfx_update(s->con, 0, 0, NUM_COLS, NUM_ROWS); return; } if (!s->redraw) { return; } // Adjust the white level to compensate for the set brightness. // brightness = 0: 255 in maps to 170 out // brightness = 1.0: 255 in maps to 255 out float brightness = s->backlight_enabled ? s->brightness : 0.0; int max_val = 170 + (255 - 170) * brightness; /* set colours according to bpp */ switch (bpp) { case 8: colour_on = rgb_to_pixel8(max_val, max_val, max_val); colour_off = rgb_to_pixel8(0x00, 0x00, 0x00); break; case 15: colour_on = rgb_to_pixel15(max_val, max_val, max_val); colour_off = rgb_to_pixel15(0x00, 0x00, 0x00); break; case 16: colour_on = rgb_to_pixel16(max_val, max_val, max_val); colour_off = rgb_to_pixel16(0x00, 0x00, 0x00); case 24: colour_on = rgb_to_pixel24(max_val, max_val, max_val); colour_off = rgb_to_pixel24(0x00, 0x00, 0x00); break; case 32: colour_on = rgb_to_pixel32(max_val, max_val, max_val); colour_off = rgb_to_pixel32(0x00, 0x00, 0x00); break; default: return; } for (y = 0; y < NUM_ROWS; y++) { for (x = 0; x < NUM_COLS; x++) { /* Rotate display - installed 'upside-down' in pebble. */ int xr = NUM_COLS - 1 - x; int yr = NUM_ROWS - 1 - y; bool on = s->framebuffer[yr * NUM_COL_BYTES + xr / 8] & 1 << (xr % 8); colour = on ? colour_on : colour_off; switch(bpp) { case 8: *((uint8_t *)d) = colour; d++; break; case 15: case 16: *((uint16_t *)d) = colour; d += 2; break; case 24: abort(); case 32: *((uint32_t *)d) = colour; d += 4; break; } } } dpy_gfx_update(s->con, 0, 0, NUM_COLS, NUM_ROWS); s->redraw = false; }