Compositing test.
This commit is contained in:
parent
119bcf6913
commit
cbcf098e5b
@ -38,6 +38,11 @@ clean:
|
||||
@${CC} ${CFLAGS} -s -o $@ $< lib/sha2.o ${ERRORS}
|
||||
@${END} "CC" "$< [w/libs]"
|
||||
|
||||
../hdd/bin/compositor: compositor.c lib/graphics.o lib/list.o
|
||||
@${BEG} "CC" "$< [w/libs]"
|
||||
@${CC} ${CFLAGS} -s -I ../util/toaru-toolchain/i686-pc-toaru/include/freetype2/ -o $@ $< lib/graphics.o lib/list.o ../util/toaru-toolchain/i686-pc-toaru/lib/libfreetype.a ${ERRORS}
|
||||
@${END} "CC" "$< [w/libs]"
|
||||
|
||||
../hdd/bin/%: %.cpp
|
||||
@${BEG} "CPP" "$<"
|
||||
@${CPP} ${CPPFLAGS} -s -o $@ $< ${ERRORS}
|
||||
|
166
userspace/compositor.c
Normal file
166
userspace/compositor.c
Normal file
@ -0,0 +1,166 @@
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
*
|
||||
* Window Compositor
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <syscall.h>
|
||||
#include <stdint.h>
|
||||
#include "lib/graphics.h"
|
||||
#include "lib/list.h"
|
||||
|
||||
typedef struct {
|
||||
uint32_t wid; /* Window identifier */
|
||||
uint32_t owner; /* Owning process */
|
||||
|
||||
uint16_t width; /* Buffer width in pixels */
|
||||
uint16_t height; /* Buffer height in pixels */
|
||||
|
||||
int32_t x; /* X coordinate of upper-left corner */
|
||||
int32_t y; /* Y coordinate of upper-left corner */
|
||||
uint16_t z; /* Stack order */
|
||||
|
||||
void * buffer; /* Window buffer */
|
||||
} window_t;
|
||||
|
||||
#define TO_WINDOW_OFFSET(x,y) (((x) - window->x) + ((y) - window->y) * window->width)
|
||||
#define DIRECT_OFFSET(x,y) ((x) + (y) * window->width)
|
||||
|
||||
list_t * window_list;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
uint8_t is_between(int32_t lo, int32_t hi, int32_t val) {
|
||||
if (val >= lo && val < hi) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t is_top(window_t *window, uint16_t x, uint16_t y) {
|
||||
uint16_t index = window->z;
|
||||
foreach(node, window_list) {
|
||||
window_t * win = (window_t *)node->value;
|
||||
if (win == window) continue;
|
||||
if (win->z < index) continue;
|
||||
if (is_between(win->x, win->x + win->width, x) && is_between(win->y, win->y + win->height, y)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void redraw_window(window_t *window) {
|
||||
uint16_t _lo_x = max(window->x, 0);
|
||||
uint16_t _hi_x = min(window->x + window->width, graphics_width);
|
||||
uint16_t _lo_y = max(window->y, 0);
|
||||
uint16_t _hi_y = min(window->y + window->height, graphics_height);
|
||||
|
||||
for (uint16_t y = _lo_y; y < _hi_y; ++y) {
|
||||
for (uint16_t x = _lo_x; x < _hi_x; ++x) {
|
||||
if (is_top(window, x, y)) {
|
||||
GFX(x,y) = ((uint32_t *)window->buffer)[TO_WINDOW_OFFSET(x,y)];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void init_window(window_t *window, int32_t x, int32_t y, uint16_t width, uint16_t height, uint16_t index) {
|
||||
window->width = width;
|
||||
window->height = height;
|
||||
window->x = x;
|
||||
window->y = y;
|
||||
window->z = index;
|
||||
/* XXX */
|
||||
window->buffer = (void *)malloc(sizeof(uint32_t) * window->width * window->height);
|
||||
}
|
||||
|
||||
void window_set_point(window_t * window, uint16_t x, uint16_t y, uint32_t color) {
|
||||
((uint32_t *)window->buffer)[DIRECT_OFFSET(x,y)] = color;
|
||||
}
|
||||
|
||||
void window_draw_line(window_t * window, uint16_t x0, uint16_t x1, uint16_t y0, uint16_t y1, uint32_t color) {
|
||||
int deltax = abs(x1 - x0);
|
||||
int deltay = abs(y1 - y0);
|
||||
int sx = (x0 < x1) ? 1 : -1;
|
||||
int sy = (y0 < y1) ? 1 : -1;
|
||||
int error = deltax - deltay;
|
||||
while (1) {
|
||||
window_set_point(window, x0, y0, color);
|
||||
if (x0 == x1 && y0 == y1) break;
|
||||
int e2 = 2 * error;
|
||||
if (e2 > -deltay) {
|
||||
error -= deltay;
|
||||
x0 += sx;
|
||||
}
|
||||
if (e2 < deltax) {
|
||||
error += deltax;
|
||||
y0 += sy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void window_fill(window_t *window, uint32_t color) {
|
||||
for (uint16_t i = 0; i < window->height; ++i) {
|
||||
for (uint16_t j = 0; j < window->width; ++j) {
|
||||
((uint32_t *)window->buffer)[DIRECT_OFFSET(j,i)] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
init_graphics();
|
||||
window_list = list_create();
|
||||
|
||||
window_t wina, winb, root, panel;
|
||||
|
||||
init_window(&root, 0, 0, graphics_width, graphics_height, 0);
|
||||
list_insert(window_list, &root);
|
||||
window_fill(&root, rgb(20,20,20));
|
||||
|
||||
init_window(&panel, 0, 0, graphics_width, 24, -1);
|
||||
list_insert(window_list, &panel);
|
||||
window_fill(&panel, rgb(20,40,60));
|
||||
|
||||
init_window(&wina, 10, 10, 300, 300, 1);
|
||||
list_insert(window_list, &wina);
|
||||
window_fill(&wina, rgb(0,255,0));
|
||||
|
||||
init_window(&winb, 120, 120, 300, 300, 2);
|
||||
list_insert(window_list, &winb);
|
||||
window_fill(&winb, rgb(0,0,255));
|
||||
|
||||
redraw_window(&root); /* We only need to redraw root if things move around */
|
||||
redraw_window(&panel);
|
||||
|
||||
int16_t direction_x = 1;
|
||||
int16_t direction_y = 1;
|
||||
|
||||
while (1) {
|
||||
window_draw_line(&wina, rand() % 300, rand() % 300, rand() % 300, rand() % 300, rgb(rand() % 255,rand() % 255,rand() % 255));
|
||||
window_draw_line(&winb, rand() % 300, rand() % 300, rand() % 300, rand() % 300, rgb(rand() % 255,rand() % 255,rand() % 255));
|
||||
redraw_window(&wina);
|
||||
redraw_window(&winb);
|
||||
redraw_window(&root);
|
||||
|
||||
winb.x += direction_x;
|
||||
winb.y += direction_y;
|
||||
if (winb.x >= graphics_width - winb.width) {
|
||||
direction_x = -1;
|
||||
}
|
||||
if (winb.y >= graphics_height - winb.height) {
|
||||
direction_y = -1;
|
||||
}
|
||||
if (winb.x <= 0) {
|
||||
direction_x = 1;
|
||||
}
|
||||
if (winb.y <= 0) {
|
||||
direction_y = 1;
|
||||
}
|
||||
}
|
||||
}
|
44
userspace/lib/graphics.c
Normal file
44
userspace/lib/graphics.c
Normal file
@ -0,0 +1,44 @@
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
*
|
||||
* Graphics library
|
||||
*/
|
||||
|
||||
#include <syscall.h>
|
||||
#include <stdint.h>
|
||||
#include "graphics.h"
|
||||
|
||||
DEFN_SYSCALL0(getgraphicsaddress, 11);
|
||||
DEFN_SYSCALL1(kbd_mode, 12, int);
|
||||
DEFN_SYSCALL0(kbd_get, 13);
|
||||
DEFN_SYSCALL1(setgraphicsoffset, 16, int);
|
||||
|
||||
DEFN_SYSCALL0(getgraphicswidth, 18);
|
||||
DEFN_SYSCALL0(getgraphicsheight, 19);
|
||||
DEFN_SYSCALL0(getgraphicsdepth, 20);
|
||||
|
||||
uint16_t graphics_width = 0;
|
||||
uint16_t graphics_height = 0;
|
||||
uint16_t graphics_depth = 0;
|
||||
|
||||
/* Pointer to graphics memory */
|
||||
uint8_t * gfx_mem = 0;
|
||||
|
||||
void init_graphics() {
|
||||
graphics_width = syscall_getgraphicswidth();
|
||||
graphics_height = syscall_getgraphicsheight();
|
||||
graphics_depth = syscall_getgraphicsdepth();
|
||||
gfx_mem = (void *)syscall_getgraphicsaddress();
|
||||
}
|
||||
|
||||
uint32_t rgb(uint8_t r, uint8_t g, uint8_t b) {
|
||||
return 0xFF000000 + (r * 0x10000) + (g * 0x100) + (b * 0x1);
|
||||
}
|
||||
|
||||
uint32_t alpha_blend(uint32_t bottom, uint32_t top, uint32_t mask) {
|
||||
float a = _RED(mask) / 256.0;
|
||||
uint8_t red = _RED(bottom) * (1.0 - a) + _RED(top) * a;
|
||||
uint8_t gre = _GRE(bottom) * (1.0 - a) + _GRE(top) * a;
|
||||
uint8_t blu = _BLU(bottom) * (1.0 - a) + _BLU(top) * a;
|
||||
return rgb(red,gre,blu);
|
||||
}
|
||||
|
38
userspace/lib/graphics.h
Normal file
38
userspace/lib/graphics.h
Normal file
@ -0,0 +1,38 @@
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
*/
|
||||
#include <syscall.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define GFX_W graphics_width /* Display width */
|
||||
#define GFX_H graphics_height /* Display height */
|
||||
#define GFX_B (graphics_depth / 8) /* Display byte depth */
|
||||
|
||||
#define _RED(color) ((color & 0x00FF0000) / 0x10000)
|
||||
#define _GRE(color) ((color & 0x0000FF00) / 0x100)
|
||||
#define _BLU(color) ((color & 0x000000FF) / 0x1)
|
||||
|
||||
/*
|
||||
* Macros make verything easier.
|
||||
*/
|
||||
#define GFX(x,y) *((uint32_t *)&gfx_mem[(GFX_W * (y) + (x)) * GFX_B])
|
||||
|
||||
DECL_SYSCALL0(getgraphicsaddress);
|
||||
DECL_SYSCALL1(kbd_mode, int);
|
||||
DECL_SYSCALL0(kbd_get);
|
||||
DECL_SYSCALL1(setgraphicsoffset, int);
|
||||
|
||||
DECL_SYSCALL0(getgraphicswidth);
|
||||
DECL_SYSCALL0(getgraphicsheight);
|
||||
DECL_SYSCALL0(getgraphicsdepth);
|
||||
|
||||
uint16_t graphics_width;
|
||||
uint16_t graphics_height;
|
||||
uint16_t graphics_depth;
|
||||
|
||||
/* Pointer to graphics memory */
|
||||
uint8_t * gfx_mem;
|
||||
|
||||
|
||||
void init_graphics();
|
||||
uint32_t rgb(uint8_t r, uint8_t g, uint8_t b);
|
||||
uint32_t alpha_blend(uint32_t bottom, uint32_t top, uint32_t mask);
|
135
userspace/lib/list.c
Normal file
135
userspace/lib/list.c
Normal file
@ -0,0 +1,135 @@
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
*
|
||||
* General-purpose list implementations.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include "list.h"
|
||||
|
||||
void list_destroy(list_t * list) {
|
||||
/* Free all of the contents of a list */
|
||||
node_t * n = list->head;
|
||||
while (n) {
|
||||
free(n->value);
|
||||
n = n->next;
|
||||
}
|
||||
}
|
||||
|
||||
void list_free(list_t * list) {
|
||||
/* Free the actual structure of a list */
|
||||
node_t * n = list->head;
|
||||
while (n) {
|
||||
node_t * s = n->next;
|
||||
free(n);
|
||||
n = s;
|
||||
}
|
||||
}
|
||||
|
||||
void list_append(list_t * list, node_t * node) {
|
||||
/* Insert a node onto the end of a list */
|
||||
if (!list->tail) {
|
||||
list->head = node;
|
||||
} else {
|
||||
list->tail->next = node;
|
||||
node->prev = list->tail;
|
||||
}
|
||||
list->tail = node;
|
||||
list->length++;
|
||||
}
|
||||
|
||||
void list_insert(list_t * list, void * item) {
|
||||
/* Insert an item into a list */
|
||||
node_t * node = malloc(sizeof(node_t));
|
||||
node->value = item;
|
||||
node->next = NULL;
|
||||
node->prev = NULL;
|
||||
list_append(list, node);
|
||||
}
|
||||
|
||||
list_t * list_create() {
|
||||
/* Create a fresh list */
|
||||
list_t * out = malloc(sizeof(list_t));
|
||||
out->head = NULL;
|
||||
out->tail = NULL;
|
||||
out->length = 0;
|
||||
return out;
|
||||
}
|
||||
|
||||
node_t * list_find(list_t * list, void * value) {
|
||||
foreach(item, list) {
|
||||
if (item->value == value) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void list_remove(list_t * list, size_t index) {
|
||||
/* remove index from the list */
|
||||
if (index > list->length) return;
|
||||
size_t i = 0;
|
||||
node_t * n = list->head;
|
||||
while (i < index) {
|
||||
n = n->next;
|
||||
i++;
|
||||
}
|
||||
list_delete(list, n);
|
||||
}
|
||||
|
||||
void list_delete(list_t * list, node_t * node) {
|
||||
/* remove node from the list */
|
||||
if (node == list->head) {
|
||||
list->head = node->next;
|
||||
}
|
||||
if (node == list->tail) {
|
||||
list->tail = node->prev;
|
||||
}
|
||||
if (node->prev) {
|
||||
node->prev->next = node->next;
|
||||
}
|
||||
if (node->next) {
|
||||
node->next->prev = node->prev;
|
||||
}
|
||||
list->length--;
|
||||
}
|
||||
|
||||
node_t * list_pop(list_t * list) {
|
||||
/* Remove and return the last value in the list
|
||||
* If you don't need it, you still probably want to free it!
|
||||
* Try free(list_pop(list)); !
|
||||
* */
|
||||
if (!list->tail) return NULL;
|
||||
node_t * out = list->tail;
|
||||
list_delete(list, list->tail);
|
||||
return out;
|
||||
}
|
||||
|
||||
node_t * list_dequeue(list_t * list) {
|
||||
if (!list->head) return NULL;
|
||||
node_t * out = list->head;
|
||||
list_delete(list, list->head);
|
||||
return out;
|
||||
}
|
||||
|
||||
list_t * list_copy(list_t * original) {
|
||||
/* Create a new copy of original */
|
||||
list_t * out = list_create();
|
||||
node_t * node = original->head;
|
||||
while (node) {
|
||||
list_insert(out, node->value);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
void list_merge(list_t * target, list_t * source) {
|
||||
/* Destructively merges source into target */
|
||||
if (target->tail) {
|
||||
target->tail->next = source->head;
|
||||
} else {
|
||||
target->head = source->head;
|
||||
}
|
||||
if (source->tail) {
|
||||
target->tail = source->tail;
|
||||
}
|
||||
target->length += source->length;
|
||||
free(source);
|
||||
}
|
37
userspace/lib/list.h
Normal file
37
userspace/lib/list.h
Normal file
@ -0,0 +1,37 @@
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
*
|
||||
* General-purpose list implementations.
|
||||
*/
|
||||
#ifndef LIST_H
|
||||
#define LIST_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct node {
|
||||
struct node * next;
|
||||
struct node * prev;
|
||||
void * value;
|
||||
} __attribute__((packed)) node_t;
|
||||
|
||||
typedef struct {
|
||||
node_t * head;
|
||||
node_t * tail;
|
||||
size_t length;
|
||||
} __attribute__((packed)) list_t;
|
||||
|
||||
void list_destroy(list_t * list);
|
||||
void list_free(list_t * list);
|
||||
void list_append(list_t * list, node_t * item);
|
||||
void list_insert(list_t * list, void * item);
|
||||
list_t * list_create();
|
||||
node_t * list_find(list_t * list, void * value);
|
||||
void list_remove(list_t * list, size_t index);
|
||||
void list_delete(list_t * list, node_t * node);
|
||||
node_t * list_pop(list_t * list);
|
||||
node_t * list_dequeue(list_t * list);
|
||||
list_t * list_copy(list_t * original);
|
||||
void list_merge(list_t * target, list_t * source);
|
||||
|
||||
#define foreach(i, list) for (node_t * i = list->head; i != NULL; i = i->next)
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user