From c1bbac52d78b2e3e93fa43a5a7b3907073493216 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Fri, 30 Jun 2017 16:45:12 +0200 Subject: text widget has a constant buffer and owns the string to draw now (passing a const char * from a local stack context is not really a good idea!) added more efficiet draw method for characters in vga driver protected desktop for now against too often redraws (boolean global variable needs_redraw, this is later a soffisticated set-of-areas-to -redraw algorithm) --- src/Makefile | 2 +- src/drivers/video/vga.c | 27 ++++++++++++++++++++++++--- src/gui/desktop.c | 17 +++++++++++++++++ src/gui/desktop.h | 3 +++ src/gui/text_widget.c | 7 ++----- src/gui/text_widget.h | 4 +++- src/kernel/kernel.c | 12 ++++++------ 7 files changed, 56 insertions(+), 16 deletions(-) diff --git a/src/Makefile b/src/Makefile index bcb0da7..a6781ba 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,6 +1,6 @@ CC := gcc INCLUDES = -I. -Ilibc -Ihardware -Idrivers -Idrivers/hdi -Idrivers/hdi/ps2 -Ikernel -Igui -CFLAGS := -std=c99 -m32 -ffreestanding -O0 -g -Wall -Werror $(INCLUDES) +CFLAGS := -std=c99 -m32 -ffreestanding -O0 -g -Wall $(INCLUDES) LD := ld NASMFLAGS := -f elf32 NASM := nasm diff --git a/src/drivers/video/vga.c b/src/drivers/video/vga.c index bcd4366..647456b 100644 --- a/src/drivers/video/vga.c +++ b/src/drivers/video/vga.c @@ -254,6 +254,7 @@ bool vga_set_mode( vga_t *vga, const vga_mode_t mode ) vga->mode.segment = get_frame_buffer_segment( vga ); vga_use_z_buffer( vga, false ); + memset( vga->zbuffer, 0, sizeof( vga->zbuffer ) ); return true; } @@ -325,12 +326,12 @@ void vga_set_pixel( vga_t *vga, const int x, const int y, const vga_color_t colo void vga_draw_rectangle( vga_t *vga, const int x, const int y, const int w, const int h, const vga_color_t color ) { if( !params_ok( vga, x, y ) ) { - kernel_panic( "Pixel coordinates are out of bounds: (%d, %d), resolution is only (%d, %d)", + kernel_panic( "Rectangle start coordinates are out of bounds: (%d, %d), resolution is only (%d, %d)", x, y, vga->mode.x, vga->mode.y ); } if( !params_ok( vga, x + w, y + h ) ) { - kernel_panic( "Pixel coordinates are out of bounds: (%d, %d), resolution is only (%d, %d)", + kernel_panic( "Rectangle end coordinates are out of bounds: (%d, %d), resolution is only (%d, %d)", x + w, y + h, vga->mode.x, vga->mode.y ); } @@ -365,15 +366,35 @@ void vga_draw_char( vga_t *vga, const unsigned char c, const int x, const int y, // for now, the 34 entry, character height is 16, assuming A-Z const unsigned char *bmap = &vga_font.Bitmap[(c-32)*16]; + uint8_t fg_color_idx = get_color_index( foreground ); + uint8_t bg_color_idx = get_color_index( background ); + // should be dynamic and vga_font.Width + uint8_t data[8]; + + for( int yy = 0; yy < vga_font.Height; yy++ ) { + memset( data, bg_color_idx, sizeof( data ) ); + for( int xx = 0; xx < vga_font.Width; xx++ ) { + if( bmap[yy] & mask[xx] ) { + data[7-xx] = fg_color_idx; + } + } + uint8_t *addr = vga->base_addr + vga->mode.x * ( y + yy ) + x; + memcpy( addr, data, 8 ); + } + +// amazingly slow +/* for( int xx = 0; xx < vga_font.Width; xx++ ) { for( int yy = 0; yy < vga_font.Height; yy++ ) { if( bmap[yy] & mask[xx] ) { vga_set_pixel( vga, x + 10 - xx, y + yy, foreground ); } else { - vga_set_pixel( vga, x + 10 - xx, y + yy, background ); +// drawing only what's needed, the background is done by the widget +// vga_set_pixel( vga, x + 10 - xx, y + yy, background ); } } } +*/ } void vga_wait_for_retrace( vga_t *vga ) diff --git a/src/gui/desktop.c b/src/gui/desktop.c index 6592b52..ad4aad9 100644 --- a/src/gui/desktop.c +++ b/src/gui/desktop.c @@ -28,6 +28,7 @@ void desktop_init( desktop_t *desktop, const int w, const int h, const vga_color desktop->mouse_x = w / 2; desktop->mouse_y = h / 2; + desktop->needs_redrawing = true; desktop->base.base.vtable = (widget_vtable_t *)&desktop_vtable; desktop->base.vtable = (composite_widget_vtable_t *)&desktop_vtable; @@ -38,6 +39,10 @@ void desktop_draw( void *obj, graphics_context_t *context ) { desktop_t *desktop = obj; + if( !desktop->needs_redrawing ) { + return; + } + vga_clear_screen( context, desktop->base.base.background_color ); composite_widget_draw( obj, context ); @@ -56,16 +61,26 @@ void desktop_draw( void *obj, graphics_context_t *context ) vga_set_pixel( context, desktop->mouse_x, desktop->mouse_y + i, VGA_COLOR_WHITE ); } } + + desktop->needs_redrawing = false; } void desktop_on_mouse_down( void *obj, const int x, const int y ) { + desktop_t *desktop = obj; + composite_widget_on_mouse_down( obj, x, y ); + + desktop->needs_redrawing = true; } void desktop_on_mouse_up( void *obj, const int x, const int y ) { + desktop_t *desktop = obj; + composite_widget_on_mouse_up( obj, x, y ); + + desktop->needs_redrawing = true; } void desktop_on_mouse_move( void *obj, const int old_x, const int old_y, const int x, const int y ) @@ -76,4 +91,6 @@ void desktop_on_mouse_move( void *obj, const int old_x, const int old_y, const i desktop->mouse_y = y; composite_widget_on_mouse_move( obj, old_x, old_y, x, y ); + + desktop->needs_redrawing = true; } diff --git a/src/gui/desktop.h b/src/gui/desktop.h index a8db094..a9d1946 100644 --- a/src/gui/desktop.h +++ b/src/gui/desktop.h @@ -5,6 +5,8 @@ #define MAX_NOF_WIDGET_CHILDREN 100 +#include + typedef struct { composite_widget_vtable_t base; } desktop_vtable_t; @@ -14,6 +16,7 @@ typedef struct { desktop_vtable_t *vtable; int mouse_x; int mouse_y; + bool needs_redrawing; } desktop_t; void desktop_init( desktop_t *widget, const int w, const int h, const vga_color_t background_color ); diff --git a/src/gui/text_widget.c b/src/gui/text_widget.c index eea2613..db237af 100644 --- a/src/gui/text_widget.c +++ b/src/gui/text_widget.c @@ -24,9 +24,7 @@ void text_widget_init( text_widget_t *widget, widget_t *parent, const int x, con widget_init( &widget->base, parent, x, y, w, h, background_color ); - // TODO: const for now, caller has to preserve the text - // maybe with memory manager in place we can do this with a strdup - widget->s = s; + text_widget_set_text( widget, s ); widget->base.vtable = (widget_vtable_t *)&text_widget_vtable; widget->vtable = &text_widget_vtable; @@ -61,7 +59,6 @@ void text_widget_set_text( void *obj, const char *s ) { text_widget_t *widget = obj; - // TODO: see above - widget->s = s; + strlcpy( widget->s, s, TEXT_WIDGET_MAX_TEXT_SIZE ); } diff --git a/src/gui/text_widget.h b/src/gui/text_widget.h index 4b00b4f..7e87a3c 100644 --- a/src/gui/text_widget.h +++ b/src/gui/text_widget.h @@ -3,6 +3,8 @@ #include "widget.h" +#define TEXT_WIDGET_MAX_TEXT_SIZE 100 + typedef struct { widget_vtable_t base; void (*set_text)( void *obj, const char *s ); @@ -11,7 +13,7 @@ typedef struct { typedef struct { widget_t base; text_widget_vtable_t *vtable; - const char *s; + char s[TEXT_WIDGET_MAX_TEXT_SIZE]; } text_widget_t; void text_widget_init( text_widget_t *widget, widget_t *parent, const int x, const int y, const int w, const int h, const vga_color_t background_color, const char *s ); diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index aacfcbd..9bd3d98 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -139,7 +139,7 @@ void kernel_main( void ) // for now we are only interested in interrupts, // so we let the main thread sleep instead of // burning CPU.. -// kernel_halt( ); + kernel_halt( ); switch( global_context.mode ) { case MODE_TEXT: @@ -152,7 +152,8 @@ void kernel_main( void ) // wait for VGA retrace, assume drawing the desktop // is fast enough to finish in time (so we don't recheck - // for retrace) + // for retrace), it Z-buffering, this is done in vga_refresh + // directly, no need to do it here // vga_wait_for_retrace( &global_context.vga ); // as vga_t is equals to the graphical context for now @@ -238,6 +239,7 @@ static void handle_keyboard_event( keyboard_event_t *event, void *context ) ((composite_widget_vtable_t *)global_context->desktop.vtable)->add_child( &global_context->desktop, (widget_t *)&global_context->window2 ); char s[100]; + char *p = s; for( char c = ' '; c <= '~'; c++ ) { *p++ = c; @@ -248,7 +250,7 @@ static void handle_keyboard_event( keyboard_event_t *event, void *context ) ((composite_widget_vtable_t *)global_context->desktop.vtable)->add_child( &global_context->desktop, (widget_t *)&global_context->window3 ); text_widget_init( &global_context->widget3, (widget_t *)&global_context->window3, 1, 1, global_context->window3.base.base.w - 2, global_context->window3.base.base.h - 2, VGA_COLOR_RED, s ); -// ((composite_widget_vtable_t *)global_context->window3.vtable)->add_child( (composite_widget_t *)&global_context->window3, (widget_t *)&global_context->widget3 ); + ((composite_widget_vtable_t *)global_context->window3.vtable)->add_child( (composite_widget_t *)&global_context->window3, (widget_t *)&global_context->widget3 ); mouse_set_resolution( mouse, vga->mode.x, vga->mode.y ); } @@ -257,7 +259,7 @@ static void handle_keyboard_event( keyboard_event_t *event, void *context ) vga_use_z_buffer( &global_context->vga, true ); // draw on mode switch - ((widget_vtable_t *)global_context->desktop.vtable)->draw( &global_context->desktop, &global_context->vga ); +// ((widget_vtable_t *)global_context->desktop.vtable)->draw( &global_context->desktop, &global_context->vga ); global_context->mode = MODE_GRAPHICS; break; @@ -336,9 +338,7 @@ static void handle_mouse_event( mouse_event_t *event, void *context ) // alternative way of redrawing on mouse event // on qemu looses the mouse.. -// interrupts_disable( ); // ((widget_vtable_t *)desktop->vtable)->draw( &global_context->desktop, &global_context->vga ); -// interrupts_enable( ); break; } -- cgit v1.2.3-54-g00ecf