#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" 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 { uint16_t posx; uint16_t posy; uint16_t width; uint16_t height; uint32_t color; uint16_t active; struct pdirectory *vmem; }; static uint16_t next_window=0; #define MAX_WINDOWS 10 struct window windows[MAX_WINDOWS]; 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_rect(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; for(uint16_t x=win->posx;xposx+win->width;x++) { usery=0; userx++; for(uint16_t y=win->posy;yposy+win->height;y++) { usery++; 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; //we encoded alpha in the highest octet. 1-opaque 0-transparent //user premultiplied alpha please! uint16_t a=(0xff-((win->color&0xff000000)>>24)); uint8_t out_r=src_r+((a*dst_r)>>8); uint8_t out_g=src_g+((a*dst_g)>>8); uint8_t out_b=src_b+((a*dst_b)>>8); if(win->vmem) { if(userx<640&&usery<480)backbuffer[y*vesa_width+x]=user_vmem[userx+usery*640]; } else { backbuffer[y*vesa_width+x]=(out_r<<16)+(out_g<<8)+out_b; } } else { backbuffer[y*vesa_width+x]=0xffffff; } } } if(win->vmem) { x86_set_page_directory(mydir); } } 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_add_window(uint32_t addr) { windows[next_window].posx=100; windows[next_window].posy=100; windows[next_window].width=640; windows[next_window].height=480; windows[next_window].color=0xAAAA00AA; windows[next_window].active=0; windows[next_window].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); windows[0].posx=800; windows[0].posy=500; windows[0].width=640; windows[0].height=480; windows[0].color=0xAAAA0000; windows[0].active=0; windows[0].vmem=0; next_window++; /* windows[1].posx=200; windows[1].posy=200; windows[1].width=640; windows[1].height=480; windows[1].color=0xAA00AA00; windows[1].active=0; windows[1].vmem=0; windows[2].posx=400; windows[2].posy=300; windows[2].width=640; windows[2].height=480; windows[2].color=0xAA0000AA; windows[2].active=0; windows[2].vmem=0; */ } 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=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; } w->active=true; active=i; } else { w->active=false; } } } 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