summaryrefslogtreecommitdiff
path: root/video/compositor.c
diff options
context:
space:
mode:
Diffstat (limited to 'video/compositor.c')
-rw-r--r--video/compositor.c306
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);
}
}
- }
}