summaryrefslogtreecommitdiff
path: root/video/compositor.c
diff options
context:
space:
mode:
Diffstat (limited to 'video/compositor.c')
-rw-r--r--video/compositor.c476
1 files changed, 275 insertions, 201 deletions
diff --git a/video/compositor.c b/video/compositor.c
index 4a7a5cc..5b188a5 100644
--- a/video/compositor.c
+++ b/video/compositor.c
@@ -21,7 +21,7 @@
#define MAX_WINDOWS 50
#define MAX_PID 200
-#define MAX_INVAL 100 // max pending invalidation rectangles per process
+#define MAX_INVALID 100 // max pending invalidation rectangles per process
#define MAX_ICONS 50
void load_bmp(uint8_t *dst,char *filename);
@@ -64,15 +64,18 @@ struct window
// set on init
bool borderless; // never show borders
bool fixed; // can not be moved
+ bool no_close; // can not be moved
+
struct pdirectory *vmem; // retreive from task manager?
};
static uint16_t next_window=0;
+struct window bbwindow;
struct window windows[MAX_WINDOWS];
struct window *pid_to_win[MAX_PID];
-struct inval invalid[MAX_PID];
-uint8_t invalid_cnt[MAX_PID];
+struct inval invalid[MAX_PID][MAX_INVALID];
+uint16_t invalid_cnt[MAX_PID];
// fraembuffer info
static uint16_t vesa_width;
@@ -175,111 +178,129 @@ static void cpy_rect(uint8_t *src, uint16_t src_pitch, uint16_t src_x, uint16
}
}
-static void put_win(uint8_t *dst, struct window *win)
+static void put_win(uint8_t *dst, struct window *win,bool alpha)
{
+ bool no_smartass=false;
struct pdirectory* mydir;
+ if(win->vmem)
+ {
+ mydir=x86_get_page_directory();
+ x86_set_page_directory(win->vmem);
+ }
- //x86_cli();// do not reschedule us til ready!
- mydir=x86_get_page_directory();
- x86_set_page_directory(win->vmem);
+ for(int i=0;i<next_window;i++)
+ {
+ if(no_smartass)
+ {
+ cpy_rect(win->fb,win->width*4,
+ 0,0, // from
+ dst,vesa_pitch,
+ win->posx,win->posy,
+ win->width,win->height,
+ 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
+ );
+ }
+ else
+ {
+ uint32_t pid=windows[i].pid;
-cpy_rect(win->fb,win->width*4,0,0, // from
- dst,vesa_pitch,win->posx,win->posy, // to
- win->width,win->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
- );
+ // if too many areas invalidated refresh whole window
+ if(invalid_cnt[pid]>=MAX_INVALID)
+ {
+ invalid[pid][0].x=win->posx;
+ invalid[pid][0].y=win->posy;
+ invalid[pid][0].w=win->width;
+ invalid[pid][0].h=win->height;
+ invalid_cnt[pid]=1;
+ }
-int iconx=X_icon_lx;
-int icony=X_icon_ly;
-if(win->on_close)
-{
- iconx=X_icon_active_lx;
- icony=X_icon_active_ly;
-}
+ for(int j=0;j<invalid_cnt[pid];j++)
+ {
+ // invalidated area is in screen coords
+ struct inval *inv=&invalid[pid][j];
-cpy_rect(icon_data,vesa_pitch,iconx,icony, // from
- dst, vesa_pitch,win->posx+win->width-X_icon_width,win->posy, // to
- X_icon_width,X_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
- ,true
- );
+ int from_x=inv->x-win->posx;
+ int from_y=inv->y-win->posy;
- // iterate over invalidated rects
-
-//// while(ringbuffer_has(win->invl))
-//// {
-//// 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)
-//// {
-//// /*
-//// 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;
-////
-//// uint16_t a;
-////
-//// 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;
-////
-////
-//// 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;
-//// */
-////
-//// put_pixel_alpha(dst,x,y,(user_vmem[userx+usery*640]));
-//// }
-//// else
-//// {
-//// put_pixel(dst,x,y,(user_vmem[userx+usery*640]));
-//// }
-////
-//// usery++;
-//// }
-//// userx++;
-//// }
-//// }
- //if(win->vmem)
- //{
- x86_set_page_directory(mydir);
-// x86_sti();
- //}
+ int to_x=inv->x;
+ int width=inv->w;
+ int to_y=inv->y;
+ int height=inv->h;
+
+ if(from_x<0)
+ {
+ to_x=inv->x-from_x;
+ width=inv->w+from_x;
+ from_x=0;
+ }
+
+ if(from_y<0)
+ {
+ to_y=inv->y-from_y;
+ height=inv->h+from_y;
+ from_y=0;
+ }
- //draw boundaries
- if(option_win_borders&&win->draw_border)
+ if(win->width<width+from_x)width=win->width-from_x;
+ if(win->height<height+from_y)height=win->height-from_y;
+
+ //klog("rep from %d %d , to %d %d , size %d %d",from_x,from_y,to_x,to_y,width,height);
+
+ if(width>0&&height>0)
+ cpy_rect(win->fb,win->width*4,
+ from_x,from_y, // from
+ dst,vesa_pitch,
+ to_x,to_y,
+ width,height,
+ false,
+ 0, 0, // scaling not implemented yet anyway, not sure how to use them :P
+ true, // transparency color key
+ 0xff00ff // color key of transp
+ ,alpha
+ );
+ }
+ }
+ }
+
+ if(win->vmem)
+ {
+ x86_set_page_directory(mydir);
+ }
+
+ // CLOSE ICON //
+ if(!win->no_close)
+ {
+ int iconx=X_icon_lx;
+ int icony=X_icon_ly;
+
+ if(win->on_close)
+ {
+ iconx=X_icon_active_lx;
+ icony=X_icon_active_ly;
+ }
+
+ cpy_rect(icon_data,vesa_pitch,iconx,icony, // from
+ dst, vesa_pitch,win->posx+win->width-X_icon_width,win->posy, // to
+ X_icon_width,X_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
+ ,true
+ );
+ }
+
+ // BORDERS //
+ if(option_win_borders&&!win->borderless)
{
uint32_t border_col=0x002b36;
if(win->active)border_col=0xfdfd6e3;
-//TODO win->draw_border=false;
+
for(uint16_t x=win->posx;x<win->posx+win->width;x++)
{
put_pixel(dst,x,win->posy,border_col,vesa_pitch,vesa_depth,false); //TOP
@@ -294,20 +315,17 @@ cpy_rect(icon_data,vesa_pitch,iconx,icony, // from
//
}
-static void put_bg(uint8_t *dst)
+
+static void invalidate_all()
{
- cpy_rect(wallpaper,vesa_pitch,0,0 , // from
- dst,vesa_pitch,0,0, // to
- vesa_width,vesa_height, // 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
- );
+ invalid[0][invalid_cnt[0]].x=0;
+ invalid[0][invalid_cnt[0]].y=0;
+ invalid[0][invalid_cnt[0]].w=vesa_width;
+ invalid[0][invalid_cnt[0]].h=vesa_height;
+ invalid_cnt[0]++;
}
-static void put_mouse(uint8_t *dst)
+static void put_mouse(uint8_t *dst,bool inval)
{
static int last_put_mouse_x=0;
@@ -325,6 +343,18 @@ if(mouse_k&1)
last_put_mouse_x=mouse_x;
last_put_mouse_y=mouse_y;
+invalid[0][invalid_cnt[0]].x=mouse_x;
+invalid[0][invalid_cnt[0]].y=mouse_y;
+invalid[0][invalid_cnt[0]].w=mouse_icon_width;
+invalid[0][invalid_cnt[0]].h=mouse_icon_height;
+
+invalid_cnt[0]++;
+
+if(inval)
+{
+return;
+}
+
cpy_rect(icon_data,vesa_pitch,iconx,icony, // from
dst, vesa_pitch,mouse_x,mouse_y, // to
mouse_icon_width,mouse_icon_height, // icon dimensions
@@ -334,7 +364,6 @@ cpy_rect(icon_data,vesa_pitch,iconx,icony, // from
0xff00ff // color key of transp
,true
);
-
}
void compositor_del_window(uint32_t addr)
@@ -372,6 +401,33 @@ void compositor_init(uint16_t width, uint16_t height,uint16_t depth, uint16_t pi
load_bmp(wallpaper,"/home/miguel/wallpaper.bmp");
load_bmp(icon_data,"/home/miguel/ico.bmp");
+ // window holding background
+ windows[0].pid=0;
+ windows[0].vmem=0;
+ windows[0].fb=wallpaper;
+ windows[0].posx=0;
+ windows[0].posy=0;
+ windows[0].height=vesa_height;
+ windows[0].width=vesa_width;
+ windows[0].fixed=true;
+ windows[0].borderless=true;
+ windows[0].no_close=true;
+ next_window++;
+
+ // fake window holding backbuffer
+ bbwindow.pid=0;
+ bbwindow.vmem=0;
+ bbwindow.fb=backbuffer;
+ bbwindow.posx=0;
+ bbwindow.posy=0;
+ bbwindow.height=vesa_height;
+ bbwindow.width=vesa_width;
+ bbwindow.fixed=true;
+ bbwindow.borderless=true;
+ bbwindow.no_close=true;
+
+ invalidate_all();
+
klog("initialized composing window manager to %d x %d x %d" ,width,height,depth);
}
@@ -382,6 +438,7 @@ void compositor_wake()
void compositor_paint()
{
+
// forced max rate
if(skip_render)return;
skip_render=true;
@@ -398,19 +455,29 @@ void compositor_paint()
last=now;
frames=0;
}
-
- //wallpaper
- //put_bg(backbuffer);
- for(int i=next_window-1;i>=0;i--)
+ for(int i=0;i<next_window;i++)
{
- put_win(backbuffer,&windows[i]);
+ x86_cli();
+ put_win(backbuffer,&windows[i],true);
+ x86_sti();
}
- put_mouse(backbuffer);
+ put_mouse(backbuffer,false);
+
+ // TODO: only rects too!
+ //memcpy(VMEM_FRAMEBUFFER,backbuffer,vesa_pitch*vesa_height);
+ put_win(VMEM_FRAMEBUFFER,&bbwindow,false);
+
+ // reset counts
+ for(int i=next_window-1;i>=0;i--)
+ {
+ uint32_t pid=windows[i].pid;
+ invalid_cnt[pid]=0;
+ }
+
+ put_mouse(backbuffer,true);//invalidate only
- // TODO: only rects
- memcpy(VMEM_FRAMEBUFFER,backbuffer,vesa_pitch*vesa_height);
}
void check_win_pos(struct window *w)
@@ -449,10 +516,8 @@ void compositor_mouse_handle(int16_t diff_x,int16_t diff_y, uint8_t key)
mouse_y+=diff_y;
mouse_k=key;
-
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;
@@ -465,63 +530,68 @@ void compositor_mouse_handle(int16_t diff_x,int16_t diff_y, uint8_t key)
int active=-1;
bool active_win=false;
- for(int i=0;i<next_window;i++)
+ // top most window first
+ for(int i=next_window;i>=0;i--)
{
struct window *w=&windows[i];
w->on_close=false;
- 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;
-
- w->posy-=last_mouse_y-mouse_y;
- last_mouse_y=mouse_y;
- check_win_pos(w);
+ if(w->fixed)continue;
- w->draw_border=true;
-
- }
- else
- {
- w->draw_meat=true;
- if(lastkey&1)
- {
- w->draw_border=true;
- 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);
- }
-
- }
+ 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;
+////
+//// w->posy-=last_mouse_y-mouse_y;
+//// last_mouse_y=mouse_y;
+////
+//// check_win_pos(w);
+////
+//// w->draw_border=true;
+////
+//// }
+//// else
+//// {
+//// w->draw_meat=true;
+//// if(lastkey&1)
+//// {
+//// w->draw_border=true;
+//// 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;
@@ -530,12 +600,11 @@ void compositor_mouse_handle(int16_t diff_x,int16_t diff_y, uint8_t key)
}
else
{
-
-
- w->active=false;
+ w->active=false;
}
}
+ /*
if(active_win&&active!=-1&&active!=0&&(key&1))
{
struct window temp;
@@ -545,8 +614,9 @@ void compositor_mouse_handle(int16_t diff_x,int16_t diff_y, uint8_t key)
pid_to_win[windows[0].pid]=&windows[active];
windows[0]=temp;
- pid_to_win[windows[0].pid]=&windows[0];
+ pid_to_win[windows[0].pid]=&windows[0];
}
+ */
lastkey=key;
}
@@ -603,16 +673,20 @@ void load_bmp(uint8_t *dst,char *filename)
void compositor_invalidate(uint32_t pid,uint16_t x, uint16_t y, uint16_t w, uint16_t h,uint32_t *fb)
{
-// klog("pid %d invalidating %dx%d rect at %d %d with fb addr 0x%08x",pid,w,h,x,y,fb);
+
+ // klog("pid %d invalidating %dx%d rect at %d %d with fb addr 0x%08x",pid,w,h,x,y,fb);
if(fb!=0)pid_to_win[pid]->fb=fb;
- if(invalid_cnt[pid]>=MAX_INVAL)return;//invalidation buffer is full.
+ if(invalid_cnt[pid]>=MAX_INVALID){
+// klog("compositor: invalidation buffer is full for pid: %d",pid);
+ return;//invalidation buffer is full.
- invalid[invalid_cnt[pid]].x=x;
- invalid[invalid_cnt[pid]].y=y;
- invalid[invalid_cnt[pid]].w=w;
- invalid[invalid_cnt[pid]].h=h;
- invalid_cnt[pid]++;
+ }
+ invalid[pid][invalid_cnt[pid]].x=x+pid_to_win[pid]->posx;
+ invalid[pid][invalid_cnt[pid]].y=y+pid_to_win[pid]->posy;
+ invalid[pid][invalid_cnt[pid]].w=w;
+ invalid[pid][invalid_cnt[pid]].h=h;
+ invalid_cnt[pid]++;
}
int compositor_create_window(uint32_t pid,uint16_t x, uint16_t y,uint16_t w,uint16_t h,uint16_t flags)
@@ -620,43 +694,43 @@ int compositor_create_window(uint32_t pid,uint16_t x, uint16_t y,uint16_t w,uint
klog("pid %d creating %dx%d win at %d %d with flags 0x%02x",pid,w,h,x,y,flags);
if (next_window>=MAX_WINDOWS)kpanic("max number of windows reached. increase MAX_WINDOWS");
- windows[next_window]=windows[0];
- pid_to_win[windows[0].pid]=&windows[next_window];
+ int idx=next_window;
// auto position
if(x==0xffff&&y==0xffff)
{
- windows[0].posx=mouse_x-(w/2);
- windows[0].posy=mouse_y-(h/2);
+ windows[idx].posx=mouse_x-(w/2);
+ windows[idx].posy=mouse_y-(h/2);
}
else
{
- windows[0].posx=x;
- windows[0].posy=y;
+ windows[idx].posx=x;
+ windows[idx].posy=y;
}
- windows[0].width=w;
- windows[0].height=h;
+ windows[idx].width=w;
+ windows[idx].height=h;
- check_win_pos(&windows[0]);
+ check_win_pos(&windows[idx]);
- windows[0].active=0;
+ windows[idx].active=0;
- windows[0].fb=0;
- windows[0].vmem=scheduler_get_vmem(pid);
- windows[0].pid=pid;
+ windows[idx].fb=0;
+ windows[idx].vmem=scheduler_get_vmem(pid);
+ windows[idx].pid=pid;
- windows[0].draw_border=true;
- windows[0].draw_meat=true;
+ windows[idx].draw_border=true;
+ windows[idx].draw_meat=true;
- windows[0].on_close=false;
- windows[0].borderless=flags&1;
- windows[0].fixed=flags&2;
+ windows[idx].on_close=false;
+ windows[idx].borderless=flags&1;
+ windows[idx].fixed=flags&2;
+ windows[idx].borderless=flags&1;
+ windows[idx].no_close=false;
- pid_to_win[windows[0].pid]=&windows[0];
+ pid_to_win[pid]=&windows[idx];
next_window++;
- //compositor_mouse_handle(0,0,0);
return 0;// ok
}