Skip to content

Commit

Permalink
libc: add qsort implementation
Browse files Browse the repository at this point in the history
wm: sort windows by z index
  • Loading branch information
ffwff committed Sep 6, 2019
1 parent dc19b22 commit 9497153
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 94 deletions.
6 changes: 3 additions & 3 deletions pkgs/wm/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ _download() {
build() {
_download https://raw.githubusercontent.com/dhepper/font8x8/master/font8x8_basic.h "$build_dir/font8x8_basic.h"

${opt_arch}-gcc -Wall -O2 -o $build_dir/wm $script_dir/wm.c -I$opt_toolsdir/include -L$opt_toolsdir/lib -lm -msse2
${opt_arch}-gcc -O2 -o $build_dir/samplwin $script_dir/samplwin.c -I$opt_toolsdir/include -L$opt_toolsdir/lib -lm -msse2
${opt_arch}-gcc -O2 -o $build_dir/canvwin $script_dir/canvwin.c -I$opt_toolsdir/include -L$opt_toolsdir/lib -lm -msse2
${opt_arch}-gcc -g -o $build_dir/wm $script_dir/wm.c -I$opt_toolsdir/include -L$opt_toolsdir/lib -lm -msse2
# ${opt_arch}-gcc -g -o $build_dir/samplwin $script_dir/samplwin.c -I$opt_toolsdir/include -L$opt_toolsdir/lib -lm -msse2
${opt_arch}-gcc -g -o $build_dir/canvwin $script_dir/canvwin.c -I$opt_toolsdir/include -L$opt_toolsdir/lib -lm -msse2
# ${opt_arch}-gcc -g -o $build_dir/cairowin $script_dir/cairowin.c -I$opt_toolsdir/include -L$opt_toolsdir/lib -msse2 -lcairo -lpixman-1 -lm
}

Expand Down
8 changes: 4 additions & 4 deletions pkgs/wm/canvwin.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ void canvas_ctx_draw_character(struct canvas_ctx *ctx, int xs, int ys, const cha
char *bitmap = font8x8_basic[ch];
if(canvas_ctx_get_format(ctx) != LIBCANVAS_FORMAT_RGB24)
return;
uint32_t *data = canvas_ctx_get_surface(ctx);
unsigned long *data = (unsigned long *)canvas_ctx_get_surface(ctx);
for (int x = 0; x < FONT_WIDTH; x++) {
for (int y = 0; y < FONT_HEIGHT; y++) {
if (bitmap[y] & 1 << x) {
Expand Down Expand Up @@ -81,12 +81,12 @@ int main(int argc, char **argv) {

struct wm_atom atom;
int retval = 0;
while ((retval = read(sample_win_fd_m, (char *)&atom, sizeof(atom))) >= 0) {
while ((retval = read(sample_win_fd_m, (char *)&atom, sizeof(struct wm_atom))) >= 0) {
if(retval == 0)
goto wait;
struct wm_atom respond_atom = {
.type = ATOM_RESPOND_TYPE,
.redraw.needs_redraw = 0,
.respond.retval = 0,
};
switch (atom.type) {
case ATOM_REDRAW_TYPE: {
Expand All @@ -97,7 +97,7 @@ int main(int argc, char **argv) {
case ATOM_MOVE_TYPE: {
sprite.x = atom.move.x;
sprite.y = atom.move.y;
respond_atom.redraw.needs_redraw = 1;
respond_atom.respond.retval = 1;
write(sample_win_fd_s, (char *)&respond_atom, sizeof(respond_atom));
break;
}
Expand Down
117 changes: 35 additions & 82 deletions pkgs/wm/wm.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ static void panic(const char *s) {

#define min(x, y) ((x)<(y)?(x):(y))

#define PACKET_TIMEOUT 1000000/30
#define PACKET_TIMEOUT 1000000
#define FRAME_TICK 1000000/60

/* WM State */
Expand Down Expand Up @@ -85,21 +85,22 @@ struct wm_window {
struct wm_window_prog prog;
struct wm_window_sprite sprite;
} as;
size_t z_index;
};

/* IPC */

int win_write_and_wait(struct wm_window_prog *prog,
struct wm_atom *write_atom,
struct wm_atom *respond_atom) {
struct wm_atom *write_atom,
struct wm_atom *respond_atom) {
write(prog->mfd, (char *)write_atom, sizeof(struct wm_atom));
if (waitfd(prog->sfd, PACKET_TIMEOUT) < 0) {
ftruncate(prog->mfd, 0);
ftruncate(prog->sfd, 0);
return 0;
}
// respond received
return read(prog->sfd, (char *)respond_atom, sizeof(respond_atom));
return read(prog->sfd, (char *)respond_atom, sizeof(struct wm_atom));
}

/* IMPL */
Expand All @@ -111,6 +112,7 @@ struct wm_window *wm_add_window(struct wm_state *state) {

struct wm_window *wm_add_win_prog(struct wm_state *state) {
struct wm_window *win = wm_add_window(state);
win->z_index = 1;
win->type = WM_WINDOW_PROG;

win->as.prog.mfd = create("/pipes/wm:sample:m");
Expand All @@ -127,11 +129,23 @@ struct wm_window *wm_add_win_prog(struct wm_state *state) {

struct wm_window *wm_add_sprite(struct wm_state *state, struct wm_window_sprite *sprite) {
struct wm_window *win = wm_add_window(state);
win->z_index = 1;
win->type = WM_WINDOW_SPRITE;
win->as.sprite = *sprite;
return win;
}

int wm_sort_windows_by_z_compar(const void *av, const void *bv) {
const struct wm_window *a = av, *b = bv;
if (a->z_index < b->z_index) return -1;
else if(a->z_index == b->z_index) return 0;
return 1;
}

void wm_sort_windows_by_z(struct wm_state *state) {
qsort(state->windows, state->nwindows, sizeof(struct wm_window), wm_sort_windows_by_z_compar);
}

int main(int argc, char **argv) {
int fb_fd = open("/fb0", 0);

Expand All @@ -154,7 +168,8 @@ int main(int argc, char **argv) {
.type = GFX_BITBLIT_COLOR
}
};
wm_add_sprite(&wm, &pape_spr);
struct wm_window *win = wm_add_sprite(&wm, &pape_spr);
win->z_index = 0;
}

// mouse
Expand All @@ -179,19 +194,24 @@ int main(int argc, char **argv) {
mouse_spr.sprite.width = w;
mouse_spr.sprite.height = h;
filter_data_with_alpha(&mouse_spr.sprite);
wm_add_sprite(&wm, &mouse_spr);

wm.mouse_win = wm_add_sprite(&wm, &mouse_spr);
wm.mouse_win->z_index = (size_t)-1;
}

// sample win
char *spawn_argv[] = {"canvwin", NULL};
spawnv("canvwin", (char **)spawn_argv);
wm_add_win_prog(&wm);

wm_sort_windows_by_z(&wm);

// disable console
ioctl(STDOUT_FILENO, TIOCGSTATE, 0);

// control pipe
// int control_fd = create("/pipes/wm");

// sample win
char *spawn_argv[] = { "canvwin", NULL };
spawnv("canvwin", (char**)spawn_argv);

wm.needs_redraw = 1;

while(1) {
Expand Down Expand Up @@ -226,7 +246,7 @@ int main(int argc, char **argv) {
int retval = win_write_and_wait(&win->as.prog, &redraw_atom, &respond_atom);

if (retval > 0) {
if (respond_atom.redraw.needs_redraw)
if (respond_atom.respond.retval)
wm.needs_redraw = 1;
}
break;
Expand All @@ -237,80 +257,13 @@ int main(int argc, char **argv) {
}
}
}
if (wm.needs_redraw) {
ioctl(fb_fd, GFX_SWAPBUF, 0);
wm.needs_redraw = 0;
}
// TODO: consistent frame rate
usleep(FRAME_TICK);
}

#if 0
int needs_redraw = 1;
int retval;

while (1) {
// wallpaper
ioctl(fb_fd, GFX_BITBLIT, &pape_spr);

// windows
if (needs_redraw) {
struct wm_atom redraw_atom = {
.type = ATOM_REDRAW_TYPE
};
struct wm_atom respond_atom;
retval = wm_write_and_wait(sample_win_fd_m, sample_win_fd_s, &redraw_atom, &respond_atom);

if(retval > 0) {
if (respond_atom.redraw.needs_redraw)
needs_redraw = 1;
}
}

// mouse
struct mouse_packet mouse_packet;
read(mouse_fd, (char *)&mouse_packet, sizeof(mouse_packet));

unsigned int speed = __builtin_ffs(mouse_packet.x + mouse_packet.y);
if(mouse_packet.x != 0) {
// left = negative
mouse_spr.x += mouse_packet.x * speed;
mouse_spr.x = min(mouse_spr.x, ws.ws_col);
needs_redraw = 1;
}
if (mouse_packet.y != 0) {
// bottom = negative
mouse_spr.y -= mouse_packet.y * speed;
mouse_spr.y = min(mouse_spr.y, ws.ws_row);
needs_redraw = 1;
}
if ((mouse_packet.attr_byte & MOUSE_ATTR_LEFT_BTN) != 0) {
struct wm_atom atom = {
.type = ATOM_MOVE_TYPE,
.move = (struct wm_atom_move){
.x = mouse_spr.x,
.y = mouse_spr.y,
}
};
write(sample_win_fd_m, (char *)&atom, sizeof(atom));
waitfd(sample_win_fd_s, PACKET_TIMEOUT);

struct wm_atom respond_atom;
read(sample_win_fd_s, (char *)&respond_atom, sizeof(respond_atom));
if (respond_atom.redraw.needs_redraw) {
needs_redraw = 1;
}
}
if(needs_redraw)
ioctl(fb_fd, GFX_BITBLIT, &mouse_spr);

if (needs_redraw) {
ioctl(fb_fd, GFX_SWAPBUF, 0);
}
ioctl(fb_fd, GFX_SWAPBUF, 0);
//if (wm.needs_redraw || 1) {
// wm.needs_redraw = 0;
//}
// TODO: consistent frame rate
usleep(FRAME_TICK);
}
#endif

return 0;
}
5 changes: 5 additions & 0 deletions pkgs/wm/wm.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,16 @@ struct wm_atom_redraw {
int needs_redraw;
};

struct wm_atom_respond {
int retval;
};

struct wm_atom {
int type;
union {
struct wm_atom_redraw redraw;
struct wm_atom_move move;
struct wm_atom_respond respond;
};
};

Expand Down
122 changes: 117 additions & 5 deletions userspace/libc/src/functions/arch/shim/qsort.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,120 @@
#include <stdlib.h>

void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *)) {
// TODO
abort();
return;
/* This implementation is taken from Paul Edward's PDPCLIB.
Original code is credited to Raymond Gardner, Englewood CO.
Minor mods are credited to Paul Edwards.
Some reformatting and simplification done by Martin Baute.
All code is still Public Domain.
*/

static inline void memswp(char *i, char *j, size_t size) {
char tmp;
do {
tmp = *i;
*i++ = *j;
*j++ = tmp;
} while (--size);
}

/* For small sets, insertion sort is faster than quicksort.
T is the threshold below which insertion sort will be used.
Must be 3 or larger.
*/
#define T 7

/* Macros for handling the QSort stack */
#define PREPARE_STACK char * stack[STACKSIZE]; char * * stackptr = stack
#define PUSH( base, limit ) stackptr[0] = base; stackptr[1] = limit; stackptr += 2
#define POP( base, limit ) stackptr -= 2; base = stackptr[0]; limit = stackptr[1]
/* TODO: Stack usage is log2( nmemb ) (minus what T shaves off the worst case).
Worst-case nmemb is platform dependent and should probably be
configured through _PDCLIB_config.h.
*/
#define STACKSIZE 64

void qsort( void * base, size_t nmemb, size_t size, int (*compar)( const void *, const void * ) )
{
char * i;
char * j;
size_t thresh = T * size;
char * base_ = (char *)base;
char * limit = base_ + nmemb * size;
PREPARE_STACK;

for ( ;; )
{
if ( (size_t)( limit - base_ ) > thresh ) /* QSort for more than T elements. */
{
/* We work from second to last - first will be pivot element. */
i = base_ + size;
j = limit - size;
/* We swap first with middle element, then sort that with second
and last element so that eventually first element is the median
of the three - avoiding pathological pivots.
TODO: Instead of middle element, chose one randomly.
*/
memswp( ( ( ( (size_t)( limit - base_ ) ) / size ) / 2 ) * size + base_, base_, size );
if ( compar( i, j ) > 0 ) memswp( i, j, size );
if ( compar( base_, j ) > 0 ) memswp( base_, j, size );
if ( compar( i, base_ ) > 0 ) memswp( i, base_, size );
/* Now we have the median for pivot element, entering main Quicksort. */
for ( ;; )
{
do
{
/* move i right until *i >= pivot */
i += size;
} while ( compar( i, base_ ) < 0 );
do
{
/* move j left until *j <= pivot */
j -= size;
} while ( compar( j, base_ ) > 0 );
if ( i > j )
{
/* break loop if pointers crossed */
break;
}
/* else swap elements, keep scanning */
memswp( i, j, size );
}
/* move pivot into correct place */
memswp( base_, j, size );
/* larger subfile base / limit to stack, sort smaller */
if ( j - base_ > limit - i )
{
/* left is larger */
PUSH( base_, j );
base_ = i;
}
else
{
/* right is larger */
PUSH( i, limit );
limit = j;
}
}
else /* insertion sort for less than T elements */
{
for ( j = base_, i = j + size; i < limit; j = i, i += size )
{
for ( ; compar( j, j + size ) > 0; j -= size )
{
memswp( j, j + size, size );
if ( j == base_ )
{
break;
}
}
}
if ( stackptr != stack ) /* if any entries on stack */
{
POP( base_, limit );
}
else /* else stack empty, done */
{
break;
}
}
}
}

0 comments on commit 9497153

Please sign in to comment.