#include "compositor.h" #include "syscalls.h" #include "kernel.h" #include "kmalloc.h" #include "log.h" #include "vmem.h" #include "timer.h" #include "asm_x86.h" #include "mount.h" #include "fd.h" #include "lib/string/string.h" #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; 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 uint16_t next_window=0; static uint16_t next_x=50; static uint16_t next_y=50; static uint16_t vesa_width; static uint16_t vesa_height; static uint16_t vesa_pitch; static uint16_t mouse_x=100; static uint16_t mouse_y=100; static uint16_t mouse_k; static bool skip_render; static bool skip_render2; static void put_pixel(int x,int y, uint32_t color) { vmem[y*vesa_width+x]=color; } 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); } 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;xposx+win->width;x++) { usery=0; for(uint16_t y=win->posy;yposy+win->height;y++) { if(!win->active) { 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)); } //we encoded alpha in the highest octet. 1-opaque 0-transparent //no premultiplied alpha. TODO: change maybe? // 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; } } usery++; } userx++; } if(win->vmem) { x86_set_page_directory(mydir); x86_sti(); } //draw boundaries for(uint16_t x=win->posx;xposx+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;yposy+win->height;y++) { backbuffer[(y)*vesa_width+(win->posx)]=0xffffff; //LEFT backbuffer[(y)*vesa_width+win->posx+win->width-1]=0xffffff; //RIGHT } // } static void put_mouse() { if(mouse_k&1) { for(int i=0;i<1;i++) for(int j=0;j=MAX_WINDOWS)kpanic("max number of windows reached. increase MAX_WINDOWS"); windows[next_window]=windows[0]; windows[0].posx=next_x; windows[0].posy=next_y; next_x+=100; next_y+=100; windows[0].width=640; windows[0].height=480; windows[0].color=0xAAAA00AA; windows[0].active=0; windows[0].vmem=addr; windows[0].pid=pid; next_window++; compositor_mouse_handle(200,200,0); } void compositor_init(uint16_t width, uint16_t height, uint16_t pitch) { vesa_width=width; vesa_height=height; klog("initialized composing window manager to %d x %d",width,height); } void compositor_wake() { skip_render=false; } void compositor_wake2() { skip_render2=false; } void compositor_swap_buffers() { if(skip_render||skip_render2)return; skip_render=true; skip_render2=true; 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); for(int i=next_window-1;i>=0;i--) { put_win(&windows[i]); } put_mouse(); memcpy(VMEM_FRAMEBUFFER,backbuffer,vesa_height*vesa_width*4);// TODO optimize? rects only too? first=false; } void compositor_kb_handle(char c) { for(int i=0;iactive) { // klog("writing [%c] to window with pid [%d]",c,w->pid); fd_write(get_tty(w->pid),c); } } } void compositor_mouse_handle(uint16_t x,uint16_t y, uint8_t key) { //klog("mouse: %d %d",x,y); static int last_mouse_x; static int last_mouse_y; if(!(key&1)) { last_mouse_x=x; last_mouse_y=y; } mouse_x=x; mouse_y=y; mouse_k=key; int active=-1; for(int i=0;iw->posx&&xposx+w->width&&y>w->posy&&yposy+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>=1920)w->posx=1920-640; if(w->posy+w->height>=1080)w->posy=1080-480; } w->active=true; active=i; } else { w->active=false; } } if(active!=-1&&active!=0&&(key&1)) { struct window temp; temp=windows[active]; windows[active]=windows[0]; windows[0]=temp; } } // 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; } void compositor_set_background(char *ppm_raw_filename) { // uint64_t t=timer_get_ms()/333; /* klog("loading bg..."); fd bg=mount_file_open(ppm_raw_filename); uint32_t i=0; for(int y=0;y