/* sortix.c * Sortix display(1) support * (c) 2021 Juhani 'nortti' Krekelä * This file is a part of the Links program, released under GPL. */ #include "cfg.h" #ifdef GRDRV_SORTIX #include //debg #include #include #include #include #include "links.h" static int default_window_width = 600; static int default_window_height = 500; static struct display_connection* connection; static struct display_event_handlers event_handlers; struct graphics_driver sortix_driver; static void sortix_process_events(void *data) { (void) data; warnx("sortix_process_events");//debg while (display_poll_event(connection, &event_handlers) == 0); } static unsigned char *sortix_init_driver(unsigned char *param, unsigned char *display) { if (param && *param) errx(1, "param %s", param); if (display && *display) errx(1, "display %s", display); connection = display_connect_default(); if (!connection && errno == ECONNREFUSED) return "TODO: display_spawn"; if (!connection) return "TODO: Proper error reporting"; sortix_driver.get_color = get_color_fn(sortix_driver.depth); set_handlers(display_connection_fd(connection), sortix_process_events, NULL, NULL); return NULL; } struct window_data { uint32_t window_id; struct framebuffer fb; }; static struct graphics_device *sortix_init_device(void) { struct graphics_device *dev = mem_calloc(sizeof(struct graphics_device)); dev->size.x1 = 0; dev->size.y1 = 0; dev->size.x2 = default_window_width; dev->size.y2 = default_window_height; dev->clip = dev->size; struct window_data *window_data = mem_calloc(sizeof(struct window_data)); dev->driver_data = window_data; window_data->window_id = 0; // TODO: Overflow when multiplying window_data->fb.buffer = mem_calloc(dev->size.x2 * dev->size.y2 * sizeof(uint32_t)); window_data->fb.xres = dev->size.x2; window_data->fb.yres = dev->size.y2; window_data->fb.pitch = dev->size.x2; display_create_window(connection, window_data->window_id); display_resize_window(connection, window_data->window_id, dev->size.x2, dev->size.y2); display_show_window(connection, window_data->window_id); return dev; } static void sortix_shutdown_device(struct graphics_device *dev) { struct window_data *window_data = dev->driver_data; display_destroy_window(connection, window_data->window_id); free(window_data); } static void sortix_shutdown_driver(void) { display_disconnect(connection); } static void sortix_after_fork(void) { if (connection) display_disconnect(connection); } static unsigned char *sortix_get_driver_param(void) { return NULL; //TODO: driver parameters? } static int sortix_get_empty_bitmap(struct bitmap *dest) { // TODO: Overflow when multiplying dest->data = mem_alloc_mayfail((size_t)dest->x * (size_t)dest->y * sizeof(uint32_t)); if (!dest->data) return -1; // TODO: Overflow when multiplying dest->skip = (ssize_t)dest->x * sizeof(uint32_t); dest->flags = 0; return 0; } static void sortix_register_bitmap(struct bitmap *bmp) { } static void *sortix_prepare_strip(struct bitmap *bmp, int top, int lines) { if (!bmp->data) return NULL; // TODO: Overflow when multiplying return ((unsigned char *)bmp->data) + bmp->skip * top; } static void sortix_commit_strip(struct bitmap *bmp, int top, int lines) { } static void sortix_unregister_bitmap(struct bitmap *bmp) { if (bmp->data) mem_free(bmp->data); } static void sortix_draw_bitmap(struct graphics_device *dev, struct bitmap *bmp, int x1, int y1) { struct window_data *window_data = dev->driver_data; warnx("sortix_draw_bitmap(%p, %p, %i, %i)", dev, bmp, x1, y1); //debg size_t width = bmp->x; size_t height = bmp->y; for (size_t y = 0; y < height; y++) { if (window_data->fb.yres <= y1 + y) continue; for (size_t x = 0; x < width; x++) { if (window_data->fb.xres <= x1 + x) continue; void *pixel_data = ((unsigned char*)bmp->data) + y * bmp->skip + x * sizeof(uint32_t); uint32_t pixel; memcpy(&pixel, pixel_data, sizeof(uint32_t)); // Set the alpha channel (see sortix_fill_area() for further details) pixel |= 0xff000000; window_data->fb.buffer[(y1 + y) * window_data->fb.pitch + x + x1] = pixel; } } display_render_window(connection, window_data->window_id, 0, 0, window_data->fb.xres, window_data->fb.yres, window_data->fb.buffer); } static void sortix_fill_area(struct graphics_device *dev, int x1, int y1, int x2, int y2, long color) { struct window_data *window_data = dev->driver_data; size_t width = x2 - x1; size_t height = y2 - y1; // Links uses a pixel format where the top byte is clear // Sortix stores alpha there, so set it to 255 uint32_t pixel = color | 0xff000000; for (size_t y = 0; y < height; y++) { for (size_t x = 0; x < width; x++) window_data->fb.buffer[(y1 + y) * window_data->fb.pitch + x + x1] = pixel; } display_render_window(connection, window_data->window_id, 0, 0, window_data->fb.xres, window_data->fb.yres, window_data->fb.buffer); } static void sortix_draw_hline(struct graphics_device *dev, int x1, int y, int x2, long color) { sortix_fill_area(dev, x1, y, x2, y, color); } static void sortix_draw_vline(struct graphics_device *dev, int x, int y1, int y2, long color) { sortix_fill_area(dev, x, y1, x, y2, color); } static void sortix_set_title(struct graphics_device *dev, unsigned char *title) { struct window_data *window_data = dev->driver_data; display_title_window(connection, window_data->window_id, title); } struct graphics_driver sortix_driver = { (unsigned char *)"sortix", sortix_init_driver, sortix_init_device, sortix_shutdown_device, sortix_shutdown_driver, NULL, // emergency_shutdown sortix_after_fork, sortix_get_driver_param, NULL, // get_af_unix_name NULL, // get_margin NULL, // set_margin sortix_get_empty_bitmap, sortix_register_bitmap, sortix_prepare_strip, sortix_commit_strip, sortix_unregister_bitmap, sortix_draw_bitmap, NULL, // get_color, set in sortix_init_driver() sortix_fill_area, sortix_draw_hline, sortix_draw_vline, NULL, // scroll NULL, // set_clip_area NULL, // flush NULL, // block NULL, // unblock NULL, // set_palette NULL, // get_real_colors sortix_set_title, NULL, // exec NULL, // set_clipboard_text NULL, // get_clipboard_text (24 << 3) | 4, // depth: 24bpp, 4 bytes per pixel 0, 0, // size (x, y), unused GD_DONT_USE_SCROLL, //flags NULL, // param }; #endif /* GRDRV_SORTIX */