diff options
Diffstat (limited to 'video/compositor.c')
| -rw-r--r-- | video/compositor.c | 306 |
1 files changed, 163 insertions, 143 deletions
diff --git a/video/compositor.c b/video/compositor.c index 645900e..64c9689 100644 --- a/video/compositor.c +++ b/video/compositor.c @@ -1,5 +1,4 @@ #include "compositor.h" - #include "syscalls.h" #include "kernel.h" #include "kmalloc.h" @@ -15,119 +14,147 @@ #define MAX_WINDOWS 100 -static uint32_t backbuffer[VESA_MAX_WIDTH*VESA_MAX_HEIGHT]; -static uint32_t bgimage[VESA_MAX_WIDTH*VESA_MAX_HEIGHT]; -static uint32_t *vmem=VMEM_FRAMEBUFFER; - struct window { - int16_t posx; - int16_t posy; + uint32_t pid; + struct pdirectory *vmem; + + int16_t posx; + int16_t posy; uint16_t width; uint16_t height; + uint32_t color; uint16_t active; - uint32_t pid; - struct pdirectory *vmem; }; struct window windows[MAX_WINDOWS]; -static uint32_t display_width=1920; -static uint32_t display_height=1080; +static uint8_t backbuffer [VESA_MAX_WIDTH*VESA_MAX_HEIGHT*4]; +static uint8_t icons [1920*1080*4]; static uint16_t next_window=0; static uint16_t next_x=50; static uint16_t next_y=50; +static uint32_t *vmem=VMEM_FRAMEBUFFER; + static uint16_t vesa_width; static uint16_t vesa_height; +static uint16_t vesa_depth; static uint16_t vesa_pitch; -static uint16_t mouse_x=100; -static uint16_t mouse_y=100; -static uint16_t mouse_k; +// initial mouse state +static int mouse_x=100; +static int mouse_y=100; + +static int last_mouse_x; +static int last_mouse_y; + +static uint16_t mouse_k=0; + +// icon +static int mouse_icon_width=25; +static int mouse_icon_height=25; +static int mouse_icon_lx=0; +static int mouse_icon_ly=0; +static int mouse_icon_active_lx=25; +static int mouse_icon_active_ly=0; + +// costly but beautiful +static bool option_blending=false; // so disable ! :P +// ugly and cheap +static bool option_win_borders=true; // so enable static bool skip_render; static bool skip_render2; -static void put_pixel(int x,int y, uint32_t color) +/** print single pixel to dst without bound checking */ +static void put_pixel(uint8_t *dst, int x,int y, uint32_t color) { - vmem[y*vesa_width+x]=color; + uint32_t *p=dst+y*vesa_pitch+x*vesa_depth; + *p=color; +} + +/** retrieves single pixel from src without bound checking */ +static uint32_t get_pixel(uint8_t *src, int x,int y) +{ + uint32_t *p=src+y*vesa_pitch+x*vesa_depth; + return *p; +} + +static void cpy_rect(uint8_t *src, uint16_t src_x, uint16_t src_y, + uint8_t *dst, uint16_t dst_x, uint16_t dst_y, + uint16_t width, uint16_t height, + bool bnd_chk, uint8_t mult, uint8_t div, + bool transp, + uint32_t transp_key + + ) + +{ + // TODO optimize! + for(int x=0;x<width;x++) + for(int y=0;y<height;y++) + { + uint32_t val=get_pixel(src,src_x+x,src_y+y); + if(transp&&transp_key==val)continue; + // TODO : just simple workaround since i do not want to edit the ppm file :P + if(val==0)val=0xffffff; + put_pixel(dst,dst_x+x,dst_y+y,val); + } + } static void put_win(struct window *win) { - struct pdirectory* mydir; -// if(win->vmem) - // { - x86_cli();// do not reschedule us til ready! - mydir=x86_get_page_directory(); - x86_set_page_directory(win->vmem); - // } + struct pdirectory* mydir; - uint32_t *user_vmem=VMEM_USER_FRAMEBUFFER; - uint32_t userx=0; - uint32_t usery=0; + x86_cli();// do not reschedule us til ready! + mydir=x86_get_page_directory(); + x86_set_page_directory(win->vmem); + uint32_t *user_vmem=VMEM_USER_FRAMEBUFFER; + uint32_t userx=0; + uint32_t usery=0; - // iterate over complete window area + // iterate over complete window area for(uint16_t x=win->posx;x<win->posx+win->width;x++) { usery=0; for(uint16_t y=win->posy;y<win->posy+win->height;y++) { - if(!win->active) + // blending non-active windows (TODO: costly?) + if(!win->active && option_blending) { + /* uint8_t dst_b=backbuffer[y*vesa_width+x]&0xff; uint8_t dst_g=(backbuffer[y*vesa_width+x]&0xff00)>>8; uint8_t dst_r=(backbuffer[y*vesa_width+x]&0xff0000)>>16; - uint8_t src_b=win->color&0xff; - uint8_t src_g=(win->color&0xff00)>>8; - uint8_t src_r=(win->color&0xff0000)>>16; uint16_t a; - if(win->vmem) - { - uint32_t col=0xff0000; - col=user_vmem[userx+usery*640]; - src_b=col&0xff; - src_g=(col&0xff00)>>8; - src_r=(col&0xff0000)>>16; - a=0x44; - } - else - { - // just for testing - src_b=win->color&0xff; - src_g=(win->color&0xff00)>>8; - src_r=(win->color&0xff0000)>>16; - - a=(0xff-((win->color&0xff000000)>>24)); - } + uint32_t col=0xff0000; + col=user_vmem[userx+usery*640]; + uint8_t src_b=col&0xff; + uint8_t src_g=(col&0xff00)>>8; + uint8_t src_r=(col&0xff0000)>>16; + a=0x44; //we encoded alpha in the highest octet. 1-opaque 0-transparent - //no premultiplied alpha. TODO: change maybe? - // + //no premultiplied alpha. TODO: change maybe for speedup!? uint8_t out_r=((src_r*(0xff-a))>>8)+((a*dst_r)>>8); uint8_t out_g=((src_g*(0xff-a))>>8)+((a*dst_g)>>8); uint8_t out_b=((src_b*(0xff-a))>>8)+((a*dst_b)>>8); backbuffer[y*vesa_width+x]=(out_r<<16)+(out_g<<8)+out_b; + */ } else { - if(win->vmem) - { - backbuffer[y*vesa_width+x]=(user_vmem[userx+usery*640]); - } - else - { - backbuffer[y*vesa_width+x]=0xffffff; - } + put_pixel(backbuffer,x,y,(user_vmem[userx+usery*640])); } usery++; @@ -141,48 +168,44 @@ static void put_win(struct window *win) //} //draw boundaries - /* - for(uint16_t x=win->posx;x<win->posx+win->width;x++) - { - backbuffer[(win->posy)*vesa_width+x]=0xffffff; //TOP - backbuffer[(win->posy+win->height-1)*vesa_width+x]=0xffffff; //BOTTOM - //backbuffer[(win->posy+win->height-3)*vesa_width+x]=0xffffff; //BOTTOM - } - for(uint16_t y=win->posy;y<win->posy+win->height;y++) + + if(option_win_borders) { - backbuffer[(y)*vesa_width+(win->posx)]=0xffffff; //LEFT - backbuffer[(y)*vesa_width+win->posx+win->width-1]=0xffffff; //RIGHT + for(uint16_t x=win->posx;x<win->posx+win->width;x++) + { + put_pixel(backbuffer,x,win->posy,0xffffff); //TOP + put_pixel(backbuffer,x,win->posy+win->height-1,0xffffff); //BOTTOM + } + for(uint16_t y=win->posy;y<win->posy+win->height;y++) + { + put_pixel(backbuffer,win->posx,y,0xffffff); //LEFT + put_pixel(backbuffer,win->posx+win->width-1,y,0xffffff); //RIGHT + } } - */ + // } static void put_mouse() { - if(mouse_k&1) - { - for(int i=0;i<1;i++) - for(int j=0;j<display_height;j++) -// backbuffer[(mouse_y+j)*vesa_width+mouse_x+i]=0x00ff00; - backbuffer[(j)*vesa_width+mouse_x+i]=0x0044ee; - - for(int i=0;i<display_width;i++) - for(int j=0;j<1;j++) -// backbuffer[(mouse_y+j)*vesa_width+mouse_x+i]=0x00ff00; - backbuffer[(mouse_y+j)*vesa_width+i]=0x0044ee; - } - else - { - for(int i=0;i<1;i++) - for(int j=0;j<display_height;j++) -// backbuffer[(mouse_y+j)*vesa_width+mouse_x+i]=0x00ff00; - backbuffer[(j)*vesa_width+mouse_x+i]=0x000099; - - for(int i=0;i<display_width;i++) - for(int j=0;j<1;j++) -// backbuffer[(mouse_y+j)*vesa_width+mouse_x+i]=0x00ff00; - backbuffer[(mouse_y+j)*vesa_width+i]=0x000099; - } +int iconx=mouse_icon_lx; +int icony=mouse_icon_ly; + +if(mouse_k&1) +{ + iconx=mouse_icon_active_lx; + icony=mouse_icon_active_ly; +} + +cpy_rect(icons,iconx,icony, // from + backbuffer, mouse_x,mouse_y, // to + mouse_icon_width,mouse_icon_height, // icon dimensions + false, + 0, 0, // scaling not implemented yet anyway, not sure how to use them :P + true, // transparency color key + 0xffffff // color key of transp + ); + } void compositor_del_window(uint32_t addr) @@ -226,11 +249,18 @@ void compositor_add_window(uint32_t addr,uint32_t pid) compositor_mouse_handle(200,200,0); } -void compositor_init(uint16_t width, uint16_t height, uint16_t pitch) +// TODO : TEXTMODE FALLBACK! +void compositor_init(uint16_t width, uint16_t height, uint16_t depth, uint16_t pitch) { vesa_width=width; vesa_height=height; - klog("initialized composing window manager to %d x %d",width,height); + vesa_depth=depth/8; + vesa_pitch=pitch; + + klog("initialized composing window manager to %d x %d x %d" ,width,height,depth); + uint16_t expected_pitch=width*depth/8; + klog("expected pitch = %d , actual pitch = %d",expected_pitch,pitch); + if(expected_pitch!=pitch)kpanic("sorry we need to fix this. padding not supported now"); } void compositor_wake() @@ -252,9 +282,8 @@ void compositor_swap_buffers() // if(!first)return; // klog("swap"); // background - memcpy(backbuffer,bgimage,vesa_height*vesa_width*4);// TODO optimize? rects only too? +// memcpy(backbuffer,bgimage,vesa_height*vesa_width*4);// TODO optimize? rects only too? // compositor_set_background(0); - for(int i=next_window-1;i>=0;i--) { @@ -262,9 +291,12 @@ void compositor_swap_buffers() } put_mouse(); - memcpy(VMEM_FRAMEBUFFER,backbuffer,vesa_height*vesa_width*4);// TODO optimize? rects only too? + + // TODO optimize? rects only too? + memcpy(VMEM_FRAMEBUFFER,backbuffer,vesa_height*vesa_width*vesa_depth); first=false; } + void compositor_kb_handle(char c) { for(int i=0;i<MAX_WINDOWS;i++) @@ -278,29 +310,31 @@ void compositor_kb_handle(char c) } } -void compositor_mouse_handle(uint16_t x,uint16_t y, uint8_t key) +void compositor_mouse_handle(int16_t diff_x,int16_t diff_y, uint8_t key) { +// klog("%d %d %d",diff_x,diff_y,key); + mouse_x+=diff_x; + mouse_y+=diff_y; + mouse_k=key; - //klog("mouse: %d %d",x,y); - static int last_mouse_x; - static int last_mouse_y; + if(mouse_x<0)mouse_x=0; + if(mouse_y<0)mouse_y=0; + + if(mouse_x>=vesa_width-mouse_icon_width)mouse_x=vesa_width-1-mouse_icon_width; + if(mouse_y>=vesa_height-mouse_icon_height)mouse_y=vesa_height-1-mouse_icon_height; if(!(key&1)) { - last_mouse_x=x; - last_mouse_y=y; + last_mouse_x=mouse_x; + last_mouse_y=mouse_y; } - mouse_x=x; - mouse_y=y; - mouse_k=key; - int active=-1; for(int i=0;i<MAX_WINDOWS;i++) { struct window *w=&windows[i]; - if(active==-1&&x>w->posx&&x<w->posx+w->width&&y>w->posy&&y<w->posy+w->height) + if(active==-1&&mouse_x>w->posx&&mouse_x<w->posx+w->width&&mouse_y>w->posy&&mouse_y<w->posy+w->height) { if(key&1) { @@ -312,8 +346,8 @@ void compositor_mouse_handle(uint16_t x,uint16_t y, uint8_t key) if(w->posx<0)w->posx=0; if(w->posy<0)w->posy=0; - if(w->posx+w->width>=1920)w->posx=1920-640; - if(w->posy+w->height>=1080)w->posy=1080-480; + if(w->posx+w->width>=vesa_width)w->posx=vesa_width-640; + if(w->posy+w->height>=vesa_height)w->posy=vesa_height-480; } @@ -335,45 +369,33 @@ void compositor_mouse_handle(uint16_t x,uint16_t y, uint8_t key) } } -// https://stackoverflow.com/questions/3581528/how-is-the-square-root-function-implemented -double sqroot(double n){ - double lo = 0, hi = n, mid; - for(int i = 0 ; i < 10 ; i++){ - mid = (lo+hi)/2; - if(mid*mid == n) return mid; - if(mid*mid > n) hi = mid; - else lo = mid; - } - return mid; -} - +// load background image or generate one if (param == 0) void compositor_set_background(char *ppm_raw_filename) { // TODO: think about funny things to do with timer and update // some generated / or modified bg regularly // // uint64_t t=timer_get_ms()/333; // - if(ppm_raw_filename!=0) - { - klog("loading bg..."); - fd bg=mount_file_open(ppm_raw_filename); + klog("loading theme..."); + fd bg=mount_file_open(ppm_raw_filename); - uint32_t i=0; + uint32_t i=0; - for(int y=0;y<vesa_width;y++) + // read the image from left to right line by line + for(int y=0;y<1080;y++) + for(int x=0;x<1920;x++) + { { - for(int x=0;x<vesa_height;x++) - { - bgimage[i]=(fd_read(&bg)<<16)+(fd_read(&bg)<<8)+fd_read(&bg); - backbuffer[i]=bgimage[i]; - i++; - } + uint32_t val=(fd_read(&bg)<<16)+(fd_read(&bg)<<8)+fd_read(&bg); + if(x>=vesa_width)continue; + if(y>=vesa_height)continue; + put_pixel(icons,x,y,val); + i++; } - - klog("finished"); } - else - { + klog("finished"); + + // generating simple background... int center_x=vesa_width/2; int center_y=vesa_height/2; @@ -388,9 +410,7 @@ void compositor_set_background(char *ppm_raw_filename) int dist=diffx*diffx+diffy*diffy; int val = 0xff*dist/max_dist; - bgimage[x+y*vesa_width]=val; - //backbuffer[x+y*vesa_width]=valr<<16; + put_pixel(backbuffer,x,y,val); } } - } } |
