From 7a9961a9b28ab0fc5b6224df4fb7ac73d52a76f1 Mon Sep 17 00:00:00 2001 From: Kevin Lange Date: Wed, 7 Mar 2012 22:31:24 -0600 Subject: [PATCH] Wallpaper application for scalable wallpaper support --- userspace/Makefile | 2 +- userspace/compositor.c | 36 ++++++++--- userspace/lib/window.c | 4 ++ userspace/lib/window.h | 2 + userspace/wallpaper.c | 138 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 172 insertions(+), 10 deletions(-) create mode 100644 userspace/wallpaper.c diff --git a/userspace/Makefile b/userspace/Makefile index 97a9f9e4..a715701d 100644 --- a/userspace/Makefile +++ b/userspace/Makefile @@ -19,7 +19,7 @@ FREETYPE_LIB = ../util/toaru-toolchain/i686-pc-toaru/lib/libfreetype.a LIBM = ../util/toaru-toolchain/i686-pc-toaru/lib/libm.a TARGETDIR = ../hdd/bin/ -ETARGETS = terminal login compositor view game-win drawlines glogin julia-win solver donut donut-checker +ETARGETS = terminal login compositor view game-win drawlines glogin julia-win solver donut donut-checker wallpaper FTARGETS = $(ETARGETS:%=$(TARGETDIR)%) .PHONY: all clean diff --git a/userspace/compositor.c b/userspace/compositor.c index 8a63f238..335c4fec 100644 --- a/userspace/compositor.c +++ b/userspace/compositor.c @@ -259,6 +259,14 @@ void redraw_window(window_t *window, uint16_t x, uint16_t y, uint16_t width, uin } } +void reorder_window (window_t * window, uint16_t new_zed) { + if (!window) { + return; + } + + window->z = new_zed; +} + void redraw_full_window (window_t * window) { if (!window) { return; @@ -281,7 +289,7 @@ void redraw_region_slow(int32_t x, int32_t y, int32_t width, int32_t height) { depth_map[x + y * graphics_width] = window->z; } else { GFX(x,y) = (y % 2 && x % 2) ? rgb(0,0,0) : rgb(255,255,255); - depth_map[x + y * graphics_width] = window->z; + depth_map[x + y * graphics_width] = 0; } } } @@ -402,7 +410,7 @@ void process_window_command (int sig) { printf("[compositor] New window request\n"); read(pw->command_pipe, &wwt, sizeof(w_window_t)); wwt.wid = _next_wid; - init_window(pw, _next_wid++, wwt.left, wwt.top, wwt.width, wwt.height, _next_wid + 5); //XXX: an actual index + init_window(pw, _next_wid++, wwt.left, wwt.top, wwt.width, wwt.height, _next_wid); //XXX: an actual index send_window_event(pw, WE_NEWWINDOW, wwt); redraw_region_slow(0,0,graphics_width,graphics_height); break; @@ -429,6 +437,11 @@ void process_window_command (int sig) { send_window_event(pw, WE_REDRAWN, wwt); break; + case WC_REORDER: + read(pw->command_pipe, &wwt, sizeof(w_window_t)); + reorder_window(get_window_with_process(pw, wwt.wid), wwt.left); + break; + default: printf("[compositor] WARN: Unknown command type %d...\n", header.command_type); void * nullbuf = malloc(header.packet_size); @@ -753,10 +766,6 @@ void _load_dejamonovubolditalic() { #endif } -void _load_wallpaper() { - init_sprite(1, "/usr/share/wallpaper.bmp", NULL); -} - void init_base_windows () { process_windows_t * pw = malloc(sizeof(process_windows_t)); pw->pid = getpid(); @@ -767,9 +776,11 @@ void init_base_windows () { #if 1 /* Create the background window */ +#if 0 window_t * root = init_window(pw, _next_wid++, 0, 0, graphics_width, graphics_height, 0); window_draw_sprite(root, sprites[1], 0, 0); redraw_full_window(root); +#endif /* Create the panel */ window_t * panel = init_window(pw, _next_wid++, 0, 0, graphics_width, 24, 0xFFFF); @@ -968,9 +979,6 @@ int main(int argc, char ** argv) { add_startup_item("Loading font: Deja Vu Sans Mono Oblique", _load_dejamonovuitalic, 2); add_startup_item("Loading font: Deja Vu Sans Mono Bold+Oblique", _load_dejamonovubolditalic, 2); #endif -#if 1 - add_startup_item("Loading wallpaper (/usr/share/wallpaper.bmp)", _load_wallpaper, 4); -#endif foreach(node, startup_items) { run_startup_item((startup_item *)node->value); @@ -1020,6 +1028,14 @@ int main(int argc, char ** argv) { } #else + if (!fork()) { + char arg_width[10], arg_height[10]; + sprintf(arg_width, "%d", graphics_width); + sprintf(arg_height, "%d", graphics_height); + char * args[] = {"/bin/wallpaper", arg_width, arg_height, NULL}; + execve(args[0], args, NULL); + } + #if 0 if (!fork()) { char arg_width[10], arg_height[10]; @@ -1030,11 +1046,13 @@ int main(int argc, char ** argv) { } #else if (!fork()) { + waitabit(); char * args[] = {"/bin/julia-win", "200","400","400","400",NULL}; execve(args[0], args, NULL); } if (!fork()) { + waitabit(); char * args[] = {"/bin/terminal", "-w", "-f", "10", "10", NULL}; execve(args[0], args, NULL); } diff --git a/userspace/lib/window.c b/userspace/lib/window.c index 86aca002..dcd71381 100644 --- a/userspace/lib/window.c +++ b/userspace/lib/window.c @@ -314,6 +314,10 @@ void window_destroy (window_t * window) { free_window(window); } +void window_reorder (window_t * window, uint16_t new_zed) { + wins_send_command(window->wid, new_zed, 0, 0, 0, WC_REORDER, 0); +} + /* Event Processing (invoked by signal only) */ diff --git a/userspace/lib/window.h b/userspace/lib/window.h index 78931d43..c21f1893 100644 --- a/userspace/lib/window.h +++ b/userspace/lib/window.h @@ -65,6 +65,7 @@ typedef struct { #define WC_DESTROY 0x02 /* Destroy an existing window */ #define WC_DAMAGE 0x03 /* Damage window (redraw region) */ #define WC_REDRAW 0x04 /* Damage window (redraw region) */ +#define WC_REORDER 0x05 /* Set the Z-index for a window (request) */ /* Events */ #define WE_KEYDOWN 0x10 /* A key has been pressed down */ @@ -161,6 +162,7 @@ void window_redraw (window_t * window, int16_t left, int16_t top, uint16_t width void window_redraw_full (window_t * window); void window_redraw_wait (window_t * window); void window_destroy (window_t * window); +void window_reorder (window_t * window, uint16_t new_zed); w_keyboard_t * poll_keyboard(); w_mouse_t * poll_mouse(); diff --git a/userspace/wallpaper.c b/userspace/wallpaper.c new file mode 100644 index 00000000..70dee1f2 --- /dev/null +++ b/userspace/wallpaper.c @@ -0,0 +1,138 @@ +#include +#include +#include + +#include +#include FT_FREETYPE_H +#include FT_CACHE_H + +#include "lib/window.h" +#include "lib/graphics.h" + +sprite_t * sprites[128]; +sprite_t alpha_tmp; + +uint16_t win_width; +uint16_t win_height; + +int center_x(int x) { + return (win_width - x) / 2; +} + +int center_y(int y) { + return (win_height - y) / 2; +} + +void init_sprite(int i, char * filename, char * alpha) { + sprites[i] = malloc(sizeof(sprite_t)); + load_sprite(sprites[i], filename); + if (alpha) { + sprites[i]->alpha = 1; + load_sprite(&alpha_tmp, alpha); + sprites[i]->masks = alpha_tmp.bitmap; + } else { + sprites[i]->alpha = 0; + } + sprites[i]->blank = 0x0; +} + +int32_t min(int32_t a, int32_t b) { + return (a < b) ? a : b; +} + +int32_t max(int32_t a, int32_t b) { + return (a > b) ? a : b; +} + +/* Bilinear filtering from Wikipedia */ +uint32_t getBilinearFilteredPixelColor(sprite_t * tex, double u, double v) { + u *= tex->width; + v *= tex->height; + int x = floor(u); + int y = floor(v); + if (x >= tex->width) return 0; + if (y >= tex->height) return 0; + double u_ratio = u - x; + double v_ratio = v - y; + double u_o = 1 - u_ratio; + double v_o = 1 - v_ratio; + double r_ALP = 256; + if (tex->alpha) { + if (x == tex->width - 1 || y == tex->height - 1) return (SPRITE(tex,x,y) | 0xFF000000) & (0xFFFFFF + _RED(SMASKS(tex,x,y)) * 0x1000000); + r_ALP = (_RED(SMASKS(tex,x,y)) * u_o + _RED(SMASKS(tex,x+1,y)) * u_ratio) * v_o + (_RED(SMASKS(tex,x,y+1)) * u_o + _RED(SMASKS(tex,x+1,y+1)) * u_ratio) * v_ratio; + } + if (x == tex->width - 1 || y == tex->height - 1) return SPRITE(tex,x,y); + double r_RED = (_RED(SPRITE(tex,x,y)) * u_o + _RED(SPRITE(tex,x+1,y)) * u_ratio) * v_o + (_RED(SPRITE(tex,x,y+1)) * u_o + _RED(SPRITE(tex,x+1,y+1)) * u_ratio) * v_ratio; + double r_BLU = (_BLU(SPRITE(tex,x,y)) * u_o + _BLU(SPRITE(tex,x+1,y)) * u_ratio) * v_o + (_BLU(SPRITE(tex,x,y+1)) * u_o + _BLU(SPRITE(tex,x+1,y+1)) * u_ratio) * v_ratio; + double r_GRE = (_GRE(SPRITE(tex,x,y)) * u_o + _GRE(SPRITE(tex,x+1,y)) * u_ratio) * v_o + (_GRE(SPRITE(tex,x,y+1)) * u_o + _GRE(SPRITE(tex,x+1,y+1)) * u_ratio) * v_ratio; + + return rgb(r_RED,r_GRE,r_BLU) & (0xFFFFFF + (int)r_ALP * 0x1000000); +} + +void draw_sprite_scaled(sprite_t * sprite, uint16_t x, uint16_t y, uint16_t width, uint16_t height) { + int32_t _left = max(x, 0); + int32_t _top = max(y, 0); + int32_t _right = min(x + width, graphics_width - 1); + int32_t _bottom = min(y + height, graphics_height - 1); + for (uint16_t _y = 0; _y < height; ++_y) { + for (uint16_t _x = 0; _x < width; ++_x) { + if (x + _x < _left || x + _x > _right || y + _y < _top || y + _y > _bottom) + continue; + if (sprite->alpha) { + uint32_t n_color = getBilinearFilteredPixelColor(sprite, (double)_x / (double)width, (double)_y/(double)height); + uint32_t f_color = rgb(_ALP(n_color), 0, 0); + GFX(x + _x, y + _y) = alpha_blend(GFX(x + _x, y + _y), n_color, f_color); + } else { + if (SPRITE(sprite,_x,_y) != sprite->blank) { + GFX(x + _x, y + _y) = getBilinearFilteredPixelColor(sprite, (double)_x / (double)width, (double)_y/(double)height); + } + } + } + } +} + +int main (int argc, char ** argv) { + if (argc < 3) { + printf("usage: %s width height\n", argv[0]); + return -1; + } + + int width = atoi(argv[1]); + int height = atoi(argv[2]); + + win_width = width; + win_height = height; + + setup_windowing(); + + /* Do something with a window */ + window_t * wina = window_create(0,0, width, height); + assert(wina); + window_fill(wina, rgb(100,100,100)); + window_reorder (wina, 0); + init_graphics_window_double_buffer(wina); + window_redraw_full(wina); + +#if 1 + printf("Loading background...\n"); + init_sprite(0, "/usr/share/login-background.bmp", NULL); + printf("Background loaded.\n"); + draw_sprite_scaled(sprites[0], 0, 0, width, height); +#endif + +#if 0 + init_sprite(1, "/usr/share/bs.bmp", "/usr/share/bs-alpha.bmp"); + draw_sprite_scaled(sprites[1], center_x(sprites[1]->width), center_y(sprites[1]->height), sprites[1]->width, sprites[1]->height); +#endif + + flip(); + window_redraw_full(wina); + + +#if 0 + window_destroy(window); // (will close on exit) + teardown_windowing(); +#endif + + return 0; +}