diff options
Diffstat (limited to 'video')
| -rw-r--r-- | video/compositor.c | 387 | ||||
| -rw-r--r-- | video/compositor.h | 3 |
2 files changed, 334 insertions, 56 deletions
diff --git a/video/compositor.c b/video/compositor.c index 64c9689..5826c03 100644 --- a/video/compositor.c +++ b/video/compositor.c @@ -12,31 +12,58 @@ #include "lib/string/string.h" -#define MAX_WINDOWS 100 +#define MAX_WINDOWS 50 +#define MAX_ICONS 50 +ringbuffer bg_invl; + +// TODO: int16 int32 mixed nonsense +// struct window { uint32_t pid; - struct pdirectory *vmem; + ringbuffer *invl; + struct pdirectory *vmem; // retreive from task manager? int16_t posx; int16_t posy; uint16_t width; uint16_t height; - uint32_t color; uint16_t active; + bool draw_border; + bool draw_meat; +}; + +struct icon +{ + int16_t posx; + int16_t posy; + uint16_t active; + + uint32_t iconx; + uint32_t icony; + + char command[64]; + uint16_t width; + uint16_t height; }; struct window windows[MAX_WINDOWS]; +struct icon icons[MAX_ICONS]; static uint8_t backbuffer [VESA_MAX_WIDTH*VESA_MAX_HEIGHT*4]; -static uint8_t icons [1920*1080*4]; +static uint8_t bgimage [VESA_MAX_WIDTH*VESA_MAX_HEIGHT*4]; +static uint8_t icon_data [1920*1080*4]; static uint16_t next_window=0; static uint16_t next_x=50; static uint16_t next_y=50; +static uint16_t next_icon=0; +static uint16_t next_icon_x; +static uint16_t next_icon_y; + static uint32_t *vmem=VMEM_FRAMEBUFFER; static uint16_t vesa_width; @@ -58,11 +85,12 @@ 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; +static int mouse_icon_active_lx=0; +static int mouse_icon_active_ly=25; // costly but beautiful -static bool option_blending=false; // so disable ! :P +static bool option_blending=false; // so better disable ! :P// also not allowed to read from vmem! :( + // ugly and cheap static bool option_win_borders=true; // so enable @@ -72,15 +100,51 @@ static bool skip_render2; /** print single pixel to dst without bound checking */ static void put_pixel(uint8_t *dst, int x,int y, uint32_t color) { - uint32_t *p=dst+y*vesa_pitch+x*vesa_depth; - *p=color; + uint8_t *p=dst+y*vesa_pitch+x*vesa_depth; + *p++=color; // waste for 24bit... + *p++=color>>8; // waste for 24bit... + *p=color>>16; // waste for 24bit... } /** 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; + uint32_t col=0; + + uint8_t *p=src+y*vesa_pitch+x*vesa_depth; + col=(*p++); // waste for 24bit... + col+=(*p++)<<8; // waste for 24bit... + col+=(*p)<<16; // waste for 24bit... + + return col; +} + +/** + print single pixel to dst without bound checking using alpha value, + encoded alpha in the highest octet. 1-opaque 0-transparent + no premultiplied alpha. TODO: change maybe for speedup!? +**/ +static void put_pixel_alpha(uint8_t *dst, int x,int y, uint32_t color) +{ + // TODO: do not use hardcoded alpha! + uint16_t a=0xaa; + + uint32_t col=get_pixel(dst,x,y); + + // TODO: optimize!! + uint8_t dst_b=col&0xff; + uint8_t dst_g=(col&0xff00)>>8; + uint8_t dst_r=(col&0xff0000)>>16; + + uint8_t src_b=color&0xff; + uint8_t src_g=(color&0xff00)>>8; + uint8_t src_r=(color&0xff0000)>>16; + + 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); + + put_pixel(dst, x,y,(out_r<<16)+(out_g<<8)+out_b); } static void cpy_rect(uint8_t *src, uint16_t src_x, uint16_t src_y, @@ -88,10 +152,7 @@ static void cpy_rect(uint8_t *src, uint16_t src_x, uint16_t src_y, uint16_t width, uint16_t height, bool bnd_chk, uint8_t mult, uint8_t div, bool transp, - uint32_t transp_key - - ) - + uint32_t transp_key, bool alpha) { // TODO optimize! for(int x=0;x<width;x++) @@ -99,15 +160,59 @@ static void cpy_rect(uint8_t *src, uint16_t src_x, uint16_t src_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); + // TODO: quick workaround for arrow black + if(alpha) + + put_pixel_alpha(dst,dst_x+x,dst_y+y,val); + else put_pixel(dst,dst_x+x,dst_y+y,val); + } +} + +static void add_icon(char *cmd) +{ + strcpy(icons[next_icon].command,cmd); + icons[next_icon].posx=next_icon_x; + icons[next_icon].posy=next_icon_y; + icons[next_icon].active=false; + icons[next_icon].width=120; + icons[next_icon].height=120; + + icons[next_icon].iconx=next_icon*120+25; + icons[next_icon].icony=0; + next_icon_x+=130; + + next_icon++; +} + +static void put_icon(uint8_t *dst, struct icon *ico) +{ +if(ico->active) +cpy_rect(icon_data,ico->iconx,ico->icony, // from + dst, ico->posx,ico->posy, // to + ico->width,ico->height, // icon dimensions + false, + 2, 0, // scaling not implemented yet anyway, not sure how to use them :P + true, // transparency color key + 0xff00ff // color key of transp + ,false + ); +else +cpy_rect(icon_data,ico->iconx,ico->icony, // from + dst, ico->posx,ico->posy, // to + ico->width,ico->height, // icon dimensions + false, + 0, 0, // scaling not implemented yet anyway, not sure how to use them :P + true, // transparency color key + 0xff00ff // color key of transp + ,true + ); } -static void put_win(struct window *win) +static void put_win(uint8_t *dst, struct window *win) { + struct pdirectory* mydir; x86_cli();// do not reschedule us til ready! @@ -115,14 +220,24 @@ static void put_win(struct window *win) 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 - for(uint16_t x=win->posx;x<win->posx+win->width;x++) + // iterate over invalidated rects + while(ringbuffer_has(win->invl)) { - usery=0; - for(uint16_t y=win->posy;y<win->posy+win->height;y++) + int ry=ringbuffer_get(win->invl)+256*ringbuffer_get(win->invl); + int rx=ringbuffer_get(win->invl)+256*ringbuffer_get(win->invl); + int rh=ringbuffer_get(win->invl)+256*ringbuffer_get(win->invl); + int rw=ringbuffer_get(win->invl)+256*ringbuffer_get(win->invl); + if(!win->draw_meat)continue; + + uint32_t userx=rx; + uint32_t usery=ry; + + // iterate over rect area + for(uint16_t x=win->posx+rx;x<win->posx+rx+rw;x++) + { + usery=ry; + for(uint16_t y=win->posy+ry;y<win->posy+ry+rh;y++) { // blending non-active windows (TODO: costly?) if(!win->active && option_blending) @@ -141,8 +256,6 @@ static void put_win(struct window *win) 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 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); @@ -151,16 +264,18 @@ static void put_win(struct window *win) backbuffer[y*vesa_width+x]=(out_r<<16)+(out_g<<8)+out_b; */ + put_pixel_alpha(dst,x,y,(user_vmem[userx+usery*640])); } else { - put_pixel(backbuffer,x,y,(user_vmem[userx+usery*640])); + put_pixel(dst,x,y,(user_vmem[userx+usery*640])); } usery++; } userx++; } + } //if(win->vmem) //{ x86_set_page_directory(mydir); @@ -169,25 +284,50 @@ static void put_win(struct window *win) //draw boundaries - if(option_win_borders) + if(option_win_borders&&win->draw_border) { + win->draw_border=false; 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 + put_pixel(dst,x,win->posy,0xffffff); //TOP + put_pixel(dst,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 + put_pixel(dst,win->posx,y,0xffffff); //LEFT + put_pixel(dst,win->posx+win->width-1,y,0xffffff); //RIGHT } } // } +static void put_bg(uint8_t *dst) +{ + while(ringbuffer_has(&bg_invl)) + { + int ry=ringbuffer_get(&bg_invl)+256*ringbuffer_get(&bg_invl); + int rx=ringbuffer_get(&bg_invl)+256*ringbuffer_get(&bg_invl); + int rh=ringbuffer_get(&bg_invl)+256*ringbuffer_get(&bg_invl); + int rw=ringbuffer_get(&bg_invl)+256*ringbuffer_get(&bg_invl); + +cpy_rect(bgimage,rx,ry, // from + dst,rx,ry, // to + rw,rh, // icon dimensions + false, + 0, 0, // scaling not implemented yet anyway, not sure how to use them :P + false, // transparency color key + 0xffffff // color key of transp + ,false + ); -static void put_mouse() + } +} +static void put_mouse(uint8_t *dst,bool before) { + +static int last_put_mouse_x=0; +static int last_put_mouse_y=0; + int iconx=mouse_icon_lx; int icony=mouse_icon_ly; @@ -197,13 +337,31 @@ if(mouse_k&1) icony=mouse_icon_active_ly; } -cpy_rect(icons,iconx,icony, // from - backbuffer, mouse_x,mouse_y, // to +if(before) +{ +cpy_rect(bgimage,last_put_mouse_x,last_put_mouse_y, // from + dst, last_put_mouse_x,last_put_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 + false, // transparency color key 0xffffff // color key of transp + ,false + ); +return; +} + +last_put_mouse_x=mouse_x; +last_put_mouse_y=mouse_y; + +cpy_rect(icon_data,iconx,icony, // from + dst, 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 + 0xff00ff // color key of transp + ,false ); } @@ -224,7 +382,7 @@ void compositor_del_window(uint32_t addr) } } -void compositor_add_window(uint32_t addr,uint32_t pid) +void compositor_add_window(uint32_t addr,uint32_t pid,ringbuffer *r) { klog("window added"); if (next_window>=MAX_WINDOWS)kpanic("max number of windows reached. increase MAX_WINDOWS"); @@ -238,12 +396,14 @@ void compositor_add_window(uint32_t addr,uint32_t pid) next_y+=100; windows[0].width=640; - windows[0].height=480; + windows[0].height=400; - windows[0].color=0xAAAA00AA; windows[0].active=0; windows[0].vmem=addr; windows[0].pid=pid; + windows[0].invl=r; + windows[0].draw_border=true; + windows[0].draw_meat=true; next_window++; compositor_mouse_handle(200,200,0); @@ -252,15 +412,27 @@ void compositor_add_window(uint32_t addr,uint32_t pid) // TODO : TEXTMODE FALLBACK! void compositor_init(uint16_t width, uint16_t height, uint16_t depth, uint16_t pitch) { + bg_invl=ringbuffer_init(3); + vesa_width=width; vesa_height=height; vesa_depth=depth/8; vesa_pitch=pitch; + int icon_count=5; + next_icon_x=width/2-icon_count*130/2; + next_icon_y=height-130; 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"); + + add_icon("vim"); + add_icon("vim"); + add_icon("vim"); + add_icon("vim"); + add_icon("vim"); + add_icon("vim"); } void compositor_wake() @@ -274,27 +446,49 @@ void compositor_wake2() void compositor_swap_buffers() { - if(skip_render||skip_render2)return; + //if(skip_render||skip_render2)return; + if(skip_render2)return; // force rate + skip_render=true; skip_render2=true; + static frames=0; + static uint64_t last=0; + if(!last)last=timer_get_ms(); + uint64_t now=timer_get_ms(); + frames++; + if(now-last>3000) + { + klog("fps: %d",frames*1000/(now-last)); + + last=now; + frames=0; + } + + + static bool first=true; -// if(!first)return; -// klog("swap"); -// background -// memcpy(backbuffer,bgimage,vesa_height*vesa_width*4);// TODO optimize? rects only too? - // compositor_set_background(0); + if(first)memcpy(VMEM_FRAMEBUFFER,bgimage,vesa_pitch*vesa_height);// TODO optimize? rects only too?? + first=false; + put_bg(VMEM_FRAMEBUFFER); + + put_mouse(VMEM_FRAMEBUFFER,true); + for(int i=next_window-1;i>=0;i--) { - put_win(&windows[i]); + put_win(VMEM_FRAMEBUFFER,&windows[i]); } - put_mouse(); + for(int i=next_icon-1;i>=0;i--) + { + // put_icon(backbuffer,&icons[i]); + } + + put_mouse(VMEM_FRAMEBUFFER,false); // TODO optimize? rects only too? - memcpy(VMEM_FRAMEBUFFER,backbuffer,vesa_height*vesa_width*vesa_depth); - first=false; +// memcpy(VMEM_FRAMEBUFFER,backbuffer,vesa_pitch*vesa_height); } void compositor_kb_handle(char c) @@ -310,9 +504,12 @@ void compositor_kb_handle(char c) } } +// TODO: check what is active ONLY on refresh screen! void compositor_mouse_handle(int16_t diff_x,int16_t diff_y, uint8_t key) { // klog("%d %d %d",diff_x,diff_y,key); + static uint8_t lastkey; + mouse_x+=diff_x; mouse_y+=diff_y; mouse_k=key; @@ -330,14 +527,62 @@ void compositor_mouse_handle(int16_t diff_x,int16_t diff_y, uint8_t key) } int active=-1; - for(int i=0;i<MAX_WINDOWS;i++) + bool active_win=false; + + for(int i=0;i<next_icon;i++) { + struct icon *w=&icons[i]; + 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) + { + /* + w->posx-=last_mouse_x-mouse_x; + last_mouse_x=mouse_x; + w->posy-=last_mouse_y-mouse_y; + last_mouse_y=mouse_y; + + if(w->posx<0)w->posx=0; + if(w->posy<0)w->posy=0; + if(w->posx+w->width>=vesa_width)w->posx=vesa_width-640; + if(w->posy+w->height>=vesa_height)w->posy=vesa_height-480; + */ + } + + w->active=true; + active=i; + } + else + { + w->active=false; + } + } + + for(int i=0;i<next_window;i++) + { struct window *w=&windows[i]; 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) { + + w->draw_meat=false; + uint32_t xy=(w->posx<<16)|(w->posy); + uint32_t wh=(640<<16)|(400); + + /* + ringbuffer_put(&bg_invl,xy&0x000000ff); + ringbuffer_put(&bg_invl,(xy&0x0000ff00)>>8); + ringbuffer_put(&bg_invl,(xy&0x00ff0000)>>16); + ringbuffer_put(&bg_invl,(xy&0xff000000)>>24); + + ringbuffer_put(&bg_invl,wh&0x000000ff); + ringbuffer_put(&bg_invl,(wh&0x0000ff00)>>8); + ringbuffer_put(&bg_invl,(wh&0x00ff0000)>>16); + ringbuffer_put(&bg_invl,(wh&0xff000000)>>24); + */ + w->posx-=last_mouse_x-mouse_x; last_mouse_x=mouse_x; @@ -349,24 +594,51 @@ void compositor_mouse_handle(int16_t diff_x,int16_t diff_y, uint8_t key) if(w->posx+w->width>=vesa_width)w->posx=vesa_width-640; if(w->posy+w->height>=vesa_height)w->posy=vesa_height-480; + w->draw_border=true; + + } + else + { + w->draw_meat=true; + if(lastkey&1) + { + uint32_t xy=(0<<16)|(0); + uint32_t wh=(640<<16)|(400); + + ringbuffer_put(w->invl,xy&0x000000ff); + ringbuffer_put(w->invl,(xy&0x0000ff00)>>8); + ringbuffer_put(w->invl,(xy&0x00ff0000)>>16); + ringbuffer_put(w->invl,(xy&0xff000000)>>24); + + ringbuffer_put(w->invl,wh&0x000000ff); + ringbuffer_put(w->invl,(wh&0x0000ff00)>>8); + ringbuffer_put(w->invl,(wh&0x00ff0000)>>16); + ringbuffer_put(w->invl,(wh&0xff000000)>>24); + } + } w->active=true; + active_win=true; active=i; } else { + + w->active=false; } } - if(active!=-1&&active!=0&&(key&1)) + if(active_win&&active!=-1&&active!=0&&(key&1)) { struct window temp; temp=windows[active]; windows[active]=windows[0]; windows[0]=temp; } + + lastkey=key; } // load background image or generate one if (param == 0) @@ -389,7 +661,7 @@ void compositor_set_background(char *ppm_raw_filename) 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); + put_pixel(icon_data,x,y,val); i++; } } @@ -405,12 +677,17 @@ void compositor_set_background(char *ppm_raw_filename) { for(int y=0;y<vesa_height;y++) { + uint32_t val; + if(y%2) + { int diffx=center_x-x; int diffy=center_y-y; int dist=diffx*diffx+diffy*diffy; - int val = 0xff*dist/max_dist; + val = 0xaa*dist/max_dist; + } + else val=0x0; - put_pixel(backbuffer,x,y,val); + put_pixel(bgimage,x,y,val<<8); } } } diff --git a/video/compositor.h b/video/compositor.h index a7bbec4..f497d6c 100644 --- a/video/compositor.h +++ b/video/compositor.h @@ -1,4 +1,5 @@ #include <stdint.h> +#include "ringbuffer.h" void compositor_wake(); void compositor_wake2(); @@ -7,5 +8,5 @@ void compositor_set_background(char *ppm_raw_filename); void compositor_swap_buffers(); void compositor_mouse_handle(int16_t x,int16_t y, uint8_t key); void compositor_kb_handle(char c); -void compositor_add_window(uint32_t addr,uint32_t pid); +void compositor_add_window(uint32_t addr,uint32_t pid,ringbuffer *); void compositor_del_window(uint32_t addr); |
