#include "compositor.h" #include "kernel.h" #include "kmalloc.h" #include "log.h" #include "vmem.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; struct pdirectory *vmem; }; struct window windows[MAX_WINDOWS]; 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 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=x86_get_page_directory(); if(win->vmem) { 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); } //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=-5;i<5;i++) for(int j=-5;j<5;j++) backbuffer[(mouse_y+j)*vesa_width+mouse_x+i]=0x00ff00; } else { for(int i=-5;i<5;i++) for(int j=-5;j<5;j++) backbuffer[(mouse_y+i)*vesa_width+mouse_x+j]=0xff0000; } } void compositor_del_window(uint32_t addr) { for(int i=0;i=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; next_window++; } 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_swap_buffers() { static bool first=true; // if(!first)return; // klog("swap"); memcpy(backbuffer,bgimage,vesa_height*vesa_width*4);// TODO optimize? rects only too? 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_mouse_handle(uint16_t x,uint16_t y, uint8_t key) { 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; } } void compositor_set_background(char *ppm_raw_filename) { klog("loading bg..."); fd bg=mount_file_open(ppm_raw_filename); uint32_t i=0; for(int y=0;y