Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(esp_rgb): add 16bpp #90

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 49 additions & 12 deletions hw/display/esp_rgb.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,31 @@
#define RGB_VERSION_MAJOR 0
#define RGB_VERSION_MINOR 1

static void update_rgb_surface(ESPRgbState* s){
DisplaySurface *surface;
switch (s->bpp){
case BPP_32:
surface = qemu_create_displaysurface_from(
s->width, s->height,
PIXMAN_x8r8g8b8,
s->width * 4, NULL
);
break;
case BPP_16:
surface= qemu_create_displaysurface_from(
s->width, s->height,
PIXMAN_r5g6b5,
s->width * 2, NULL
);
break;
default:
warn_report("[ESP RGB] Invalid %d bpp value", s->bpp);
return;
}
surface->flags = QEMU_ALLOCATED_FLAG;
dpy_gfx_replace_surface(s->con, surface);
};

static uint64_t esp_rgb_read(void *opaque, hwaddr addr, unsigned int size)
{
ESPRgbState *s = ESP_RGB(opaque);
Expand Down Expand Up @@ -65,6 +90,10 @@ static uint64_t esp_rgb_read(void *opaque, hwaddr addr, unsigned int size)
case A_RGB_UPDATE_STATUS:
r = s->update_area;
break;

case A_RGB_BPP_VALUE:
r = s->bpp;
break;

default:
#if RGB_WARNING
Expand Down Expand Up @@ -110,7 +139,7 @@ static void esp_rgb_write(void *opaque, hwaddr addr,
s->height = MAX(s->height, 10);

/* Update the window size */
s->do_update_size = true;
s->do_update_surface = true;
break;

case A_RGB_UPDATE_STATUS:
Expand All @@ -131,6 +160,11 @@ static void esp_rgb_write(void *opaque, hwaddr addr,
s->color_content = (uint32_t) value;
break;

case A_RGB_BPP_VALUE:
s->bpp = (uint32_t) value;
s->do_update_surface = true;
break;

default:
#if RGB_WARNING
warn_report("[ESP RGB] Unsupported write to 0x%lx (%08lx)", (unsigned long) addr, (unsigned long) value);
Expand All @@ -145,9 +179,9 @@ static void rgb_update(void* opaque)
{
ESPRgbState* s = (ESPRgbState*) opaque;

if (s->con && s->do_update_size) {
qemu_console_resize(s->con, s->width, s->height);
s->do_update_size = false;
if (s->con && s->do_update_surface) {
update_rgb_surface(s);
s->do_update_surface = false;
}

if (s->con && s->update_area) {
Expand All @@ -156,12 +190,13 @@ static void rgb_update(void* opaque)

/* Since we are in a 32bpp configuration, it's enough to cast the framebuffer
* as a uint32_t pointer */
uint32_t* data = surface_data(qemu_console_surface(s->con));
const int bpp = s->bpp;
void* data = surface_data(qemu_console_surface(s->con));

/* Width and height of the area to update */
const int width = s->to_x - s->from_x;
const int height = s->to_y - s->from_y;
const int bytes_per_pixel = sizeof(uint32_t);
const int bytes_per_pixel = bpp/8;
const int total_bytes = width * height * bytes_per_pixel;

if (address_space_access_valid(&s->vram_as, src, total_bytes, false, MEMTXATTRS_UNSPECIFIED)) {
Expand All @@ -179,14 +214,14 @@ static void rgb_update(void* opaque)
/* Only perform the copy if the area is valid */
if (width > 0 && height > 0 &&
(s->from_x + width) <= s->width && (s->from_y + height) <= s->height) {

uint32_t* dest = &data[s->from_y * s->width + s->from_x];
void* dest = data + (s->from_y * s->width + s->from_x) * bytes_per_pixel;

/* Copy the pixels to the framebuffer */
for (int i = 0; i < height; i++) {
dma_memory_read(src_as, src, dest, width * bytes_per_pixel, MEMTXATTRS_UNSPECIFIED);
/* Go to the next line in the destination */
dest += s->width;
dest += s->width * bytes_per_pixel;
/* Same goes for the source */
src += width * bytes_per_pixel;
}
Expand Down Expand Up @@ -255,13 +290,15 @@ static void esp_rgb_init(Object *obj)
s->width = ESP_RGB_MAX_WIDTH;
s->height = ESP_RGB_MAX_HEIGHT;
s->update_area = false;
s->bpp = DEFAULT_BPP;

if (s->con == NULL) {
s->con = graphic_console_init(DEVICE(s), 0, &fb_ops, s);
qemu_console_resize(s->con, s->width, s->height);
uint32_t* data = surface_data(qemu_console_surface(s->con));
/* Resize and use corrent color bpp*/
update_rgb_surface(s);
void * data = surface_data(qemu_console_surface(s->con));
/* Initialize the window to black */
memset(data, 0, ESP_RGB_MAX_VRAM_SIZE);
memset(data, 0, (s->width * s->height * s->bpp) / 8);
}

/* Create a memory region that can be used as a framebuffer by the guest */
Expand Down
16 changes: 13 additions & 3 deletions include/hw/display/esp_rgb.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@
#define ESP_RGB_MAX_HEIGHT (600)
#define ESP_RGB_MAX_VRAM_SIZE (ESP_RGB_MAX_WIDTH * ESP_RGB_MAX_HEIGHT * 4)

#define DEFAULT_BPP (BPP_32)

typedef enum {
BPP_16 = 16,
BPP_32 = 32
} BppEnum;

typedef struct ESPRgbState {
SysBusDevice parent_obj;

Expand All @@ -28,7 +35,7 @@ typedef struct ESPRgbState {
/* Window size */
uint32_t width;
uint32_t height;
bool do_update_size;
bool do_update_surface;

/* Update area */
bool update_area;
Expand All @@ -37,9 +44,12 @@ typedef struct ESPRgbState {
uint32_t to_x;
uint32_t to_y;
uint32_t color_content;

/* BPP */
BppEnum bpp;
} ESPRgbState;

#define ESP_RGB_IO_SIZE (A_RGB_UPDATE_STATUS + 4)
#define ESP_RGB_IO_SIZE (A_RGB_UPDATE_STATUS + 8)

REG32(RGB_VERSION, 0x00)
FIELD(RGB_VERSION, MAJOR, 16, 16)
Expand Down Expand Up @@ -67,4 +77,4 @@ REG32(RGB_UPDATE_STATUS, 0x14)
* Automatically cleared by the hardware after window update. */
FIELD(RGB_UPDATE_STATUS, ENA, 0, 1)


REG32(RGB_BPP_VALUE, 0x18)