Compare commits

...

9 Commits

Author SHA1 Message Date
Juhani Krekelä a94cdcc43d XXX 2022-03-07 14:38:44 +02:00
Juhani Krekelä e0fae84fbf Gracefully handle errors in initialization 2022-03-07 14:38:44 +02:00
Juhani Krekelä b1bcb50982 Handle -mode 2022-03-07 14:38:44 +02:00
Juhani Krekelä 7f06430ea0 Handle events 2022-03-07 14:38:44 +02:00
Juhani Krekelä 0ed0332d6d Minimize amount of data copied to display server 2022-03-07 14:38:44 +02:00
Juhani Krekelä 40acfd7972 Further bringup and drawing routines 2022-03-07 14:38:44 +02:00
Juhani Krekelä b85a526ffc Basic bringup 2022-03-07 14:38:44 +02:00
Juhani Krekelä 08cb39b365 Add driver to the manual page 2022-03-07 14:38:44 +02:00
Juhani Krekelä c38c478545 Start work on Sortix graphics driver 2022-03-07 14:38:44 +02:00
3 changed files with 344 additions and 2 deletions

View File

@ -52,7 +52,7 @@ Run in text mode (overrides previous \-g).
.TP .TP
\f3-driver \f2<driver name>\f1 \f3-driver \f2<driver name>\f1
Graphics driver to use. Drivers are: x, svgalib, fb, directfb, pmshell, Graphics driver to use. Drivers are: x, svgalib, fb, directfb, pmshell,
atheos. atheos, sortix.
List of drivers will be shown if you give it an unknown driver. List of drivers will be shown if you give it an unknown driver.
Available drivers depend on your operating system and available libraries. Available drivers depend on your operating system and available libraries.

341
sortix.c
View File

@ -1,9 +1,350 @@
/* 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" #include "cfg.h"
#ifdef GRDRV_SORTIX #ifdef GRDRV_SORTIX
#include <sys/keycodes.h>
#include <errno.h>
#include <stdint.h>
#include <display.h>
#include <framebuffer.h>
#include "links.h" #include "links.h"
struct window_data
{
uint32_t window_id;
int modifiers;
uint32_t *buffer;
};
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; struct graphics_driver sortix_driver;
static struct graphics_device *current_dev;
static void on_disconnect(void *ctx)
{
if (current_dev->keyboard_handler)
current_dev->keyboard_handler(current_dev, KBD_CTRL_C, 0);
}
static void on_quit(void *ctx, uint32_t window_id)
{
struct window_data *window_data = current_dev->driver_data;
if (window_id != window_data->window_id) return;
if (current_dev->keyboard_handler)
current_dev->keyboard_handler(current_dev, KBD_CLOSE, 0);
}
static void on_keyboard(void *ctx, uint32_t window_id, uint32_t codepoint)
{
(void) ctx;
struct window_data *window_data = current_dev->driver_data;
if (window_id != window_data->window_id) return;
int kbkey = KBKEY_DECODE(codepoint);
if (kbkey) {
switch (kbkey) {
case KBKEY_LALT: window_data->modifiers |= KBD_ALT; break;
case -KBKEY_LALT: window_data->modifiers &= ~KBD_ALT; break;
case KBKEY_LSHIFT: case KBKEY_RSHIFT: window_data->modifiers |= KBD_SHIFT; break;
case -KBKEY_LSHIFT: case -KBKEY_RSHIFT: window_data->modifiers &= ~KBD_SHIFT; break;
case KBKEY_LCTRL: case KBKEY_RCTRL: window_data->modifiers |= KBD_CTRL; break;
case -KBKEY_LCTRL: case -KBKEY_RCTRL: window_data->modifiers &= ~KBD_CTRL; break;
}
}
if (current_dev->keyboard_handler) {
if (kbkey) codepoint = 0;
switch (codepoint) {
case '\n': codepoint = KBD_ENTER; break;
case 127: codepoint = KBD_BS; break;
case '\t': codepoint = KBD_TAB; break;
}
switch (kbkey) {
case KBKEY_ESC: codepoint = KBD_ESC; break;
case KBKEY_LEFT: codepoint = KBD_LEFT; break;
case KBKEY_RIGHT: codepoint = KBD_RIGHT; break;
case KBKEY_UP: codepoint = KBD_UP; break;
case KBKEY_DOWN: codepoint = KBD_DOWN; break;
case KBKEY_INSERT: codepoint = KBD_INS; break;
case KBKEY_DELETE: codepoint = KBD_DEL; break;
case KBKEY_HOME: codepoint = KBD_HOME; break;
case KBKEY_END: codepoint = KBD_END; break;
case KBKEY_PGUP: codepoint = KBD_PAGE_UP; break;
case KBKEY_PGDOWN: codepoint = KBD_PAGE_DOWN; break;
case KBKEY_F1: codepoint = KBD_F1; break;
case KBKEY_F2: codepoint = KBD_F2; break;
case KBKEY_F3: codepoint = KBD_F3; break;
case KBKEY_F4: codepoint = KBD_F4; break;
case KBKEY_F5: codepoint = KBD_F5; break;
case KBKEY_F6: codepoint = KBD_F6; break;
case KBKEY_F7: codepoint = KBD_F7; break;
case KBKEY_F8: codepoint = KBD_F8; break;
case KBKEY_F9: codepoint = KBD_F9; break;
case KBKEY_F10: codepoint = KBD_F10; break;
case KBKEY_F11: codepoint = KBD_F11; break;
case KBKEY_F12: codepoint = KBD_F12; break;
}
if (codepoint)
current_dev->keyboard_handler(current_dev, codepoint, window_data->modifiers);
}
}
static void on_resize(void *ctx, uint32_t window_id, uint32_t width, uint32_t height)
{
(void) ctx;
struct window_data *window_data = current_dev->driver_data;
if (window_id != window_data->window_id) return;
if (!width || !height) return;
free(window_data->buffer);
// TODO: Overflow when multiplying
window_data->buffer = mem_alloc(width * height * sizeof(uint32_t));
current_dev->size.x2 = width;
current_dev->size.y2 = height;
if (current_dev->resize_handler)
current_dev->resize_handler(current_dev);
}
static void sortix_process_events(void *data)
{
(void) data;
if (!current_dev) return;
while (display_poll_event(connection, &event_handlers) == 0);
}
static unsigned char *sortix_init_driver(unsigned char *param, unsigned char *display)
{
if (param) {
if (sscanf(param, "%ix%i", &default_window_width, &default_window_height) != 2)
return stracpy("-mode syntax is WIDTHxHEIGHT\n");
}
(void) display; // Only used by the X11 driver
connection = display_connect_default();
if (!connection && errno == ECONNREFUSED)
display_spawn(g_argc, g_argv);
if (!connection) {
char err[256];
snprintf(err, sizeof(err), "Error connecting to display: %s\n", strerror(errno));
return stracpy(err);
}
sortix_driver.get_color = get_color_fn(sortix_driver.depth);
event_handlers.disconnect_handler = on_disconnect;
event_handlers.keyboard_handler = on_keyboard;
event_handlers.quit_handler = on_quit;
event_handlers.resize_handler = on_resize;
set_handlers(display_connection_fd(connection), sortix_process_events, NULL, NULL);
return NULL;
}
static struct graphics_device *sortix_init_device(void)
{
// TODO: Multi-window support
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->buffer = mem_alloc(default_window_width * default_window_height * sizeof(uint32_t));
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);
current_dev = dev;
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->buffer);
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 x, int y)
{
CLIP_DRAW_BITMAP
struct window_data *window_data = dev->driver_data;
int pitch = dev->size.x2;
int width = bmp->x;
int height = bmp->y;
if (!width || !height)
return;
for (int bitmap_y = 0; bitmap_y < height; bitmap_y++) {
for (int bitmap_x = 0; bitmap_x < width; bitmap_x++) {
void *pixel_data = ((unsigned char*)bmp->data) + bitmap_y * bmp->skip + bitmap_x * sizeof(uint32_t);
uint32_t pixel;
memcpy(&pixel, pixel_data, sizeof(uint32_t));
// Set alpha (see sortix_fill_area() for more details)
pixel |= 0xff000000;
window_data->buffer[(y + bitmap_y) * pitch + x + bitmap_x] = pixel;
}
}
display_render_window(connection, window_data->window_id, 0, 0, dev->size.x2, dev->size.y2, window_data->buffer);
}
static void sortix_fill_area(struct graphics_device *dev, int x1, int y1, int x2, int y2, long color)
{
CLIP_FILL_AREA
struct window_data *window_data = dev->driver_data;
int pitch = dev->size.x2;
// 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 (int y = y1; y < y2; y++) {
for (int x = x1; x < x2; x++) {
window_data->buffer[y * pitch + x] = pixel;
}
}
display_render_window(connection, window_data->window_id, 0, 0, dev->size.x2, dev->size.y2, window_data->buffer);
}
static void sortix_draw_hline(struct graphics_device *dev, int x1, int y, int x2, long color)
{
CLIP_DRAW_HLINE
sortix_fill_area(dev, x1, y, x2, y + 1, color);
}
static void sortix_draw_vline(struct graphics_device *dev, int x, int y1, int y2, long color)
{
CLIP_DRAW_VLINE
sortix_fill_area(dev, x, y1, x + 1, 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 | GD_UNICODE_KEYS, //flags
NULL, // param
};
#endif /* GRDRV_SORTIX */ #endif /* GRDRV_SORTIX */

View File

@ -1,4 +1,5 @@
NAME=links NAME=links
BUILD_LIBRARIES='libbrotli? libevent? libssl libz? libzstd? lzip? openmp? xz?' BUILD_LIBRARIES='libbrotli? libevent? libjpeg libpng librsvg? libssl libtiff? libz? libzstd? lzip? openmp? xz?'
BUILD_SYSTEM=configure BUILD_SYSTEM=configure
CONFIGURE_ARGS='--enable-graphics'
LOCATION_INDEPENDENT=true LOCATION_INDEPENDENT=true