summaryrefslogtreecommitdiff
path: root/video/compositor.c
diff options
context:
space:
mode:
authorMiguel <m.i@gmx.at>2018-10-17 02:39:56 +0200
committerMiguel <m.i@gmx.at>2018-10-17 02:39:56 +0200
commit474c803c32fe055b4f09cb779f22b70d7eba8325 (patch)
treefda4241ebd53688c17379a9dd11b111c5bf5e7a0 /video/compositor.c
parent39f271589fb9db3d6a383857817b13a9bb59d981 (diff)
screen areas invalidation
Diffstat (limited to 'video/compositor.c')
-rw-r--r--video/compositor.c387
1 files changed, 332 insertions, 55 deletions
diff --git a/video/compositor.c b/video/compositor.c
index 64c9689..5826c03 100644
--- a/video/compositor.c
+++ b/video/compositor.c
@@ -12,31 +12,58 @@
#include "lib/string/string.h"
-#define MAX_WINDOWS 100
+#define MAX_WINDOWS 50
+#define MAX_ICONS 50
+ringbuffer bg_invl;
+
+// TODO: int16 int32 mixed nonsense
+//
struct window
{
uint32_t pid;
- struct pdirectory *vmem;
+ ringbuffer *invl;
+ struct pdirectory *vmem; // retreive from task manager?
int16_t posx;
int16_t posy;
uint16_t width;
uint16_t height;
- uint32_t color;
uint16_t active;
+ bool draw_border;
+ bool draw_meat;
+};
+
+struct icon
+{
+ int16_t posx;
+ int16_t posy;
+ uint16_t active;
+
+ uint32_t iconx;
+ uint32_t icony;
+
+ char command[64];
+ uint16_t width;
+ uint16_t height;
};
struct window windows[MAX_WINDOWS];
+struct icon icons[MAX_ICONS];
static uint8_t backbuffer [VESA_MAX_WIDTH*VESA_MAX_HEIGHT*4];
-static uint8_t icons [1920*1080*4];
+static uint8_t bgimage [VESA_MAX_WIDTH*VESA_MAX_HEIGHT*4];
+static uint8_t icon_data [1920*1080*4];
static uint16_t next_window=0;
static uint16_t next_x=50;
static uint16_t next_y=50;
+static uint16_t next_icon=0;
+static uint16_t next_icon_x;
+static uint16_t next_icon_y;
+
static uint32_t *vmem=VMEM_FRAMEBUFFER;
static uint16_t vesa_width;
@@ -58,11 +85,12 @@ 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;
+static int mouse_icon_active_lx=0;
+static int mouse_icon_active_ly=25;
// costly but beautiful
-static bool option_blending=false; // so disable ! :P
+static bool option_blending=false; // so better disable ! :P// also not allowed to read from vmem! :(
+
// ugly and cheap
static bool option_win_borders=true; // so enable
@@ -72,15 +100,51 @@ static bool skip_render2;
/** print single pixel to dst without bound checking */
static void put_pixel(uint8_t *dst, int x,int y, uint32_t color)
{
- uint32_t *p=dst+y*vesa_pitch+x*vesa_depth;
- *p=color;
+ uint8_t *p=dst+y*vesa_pitch+x*vesa_depth;
+ *p++=color; // waste for 24bit...
+ *p++=color>>8; // waste for 24bit...
+ *p=color>>16; // waste for 24bit...
}
/** 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;
+ uint32_t col=0;
+
+ uint8_t *p=src+y*vesa_pitch+x*vesa_depth;
+ col=(*p++); // waste for 24bit...
+ col+=(*p++)<<8; // waste for 24bit...
+ col+=(*p)<<16; // waste for 24bit...
+
+ return col;
+}
+
+/**
+ print single pixel to dst without bound checking using alpha value,
+ encoded alpha in the highest octet. 1-opaque 0-transparent
+ no premultiplied alpha. TODO: change maybe for speedup!?
+**/
+static void put_pixel_alpha(uint8_t *dst, int x,int y, uint32_t color)
+{
+ // TODO: do not use hardcoded alpha!
+ uint16_t a=0xaa;
+
+ uint32_t col=get_pixel(dst,x,y);
+
+ // TODO: optimize!!
+ uint8_t dst_b=col&0xff;
+ uint8_t dst_g=(col&0xff00)>>8;
+ uint8_t dst_r=(col&0xff0000)>>16;
+
+ uint8_t src_b=color&0xff;
+ uint8_t src_g=(color&0xff00)>>8;
+ uint8_t src_r=(color&0xff0000)>>16;
+
+ 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);
+
+ put_pixel(dst, x,y,(out_r<<16)+(out_g<<8)+out_b);
}
static void cpy_rect(uint8_t *src, uint16_t src_x, uint16_t src_y,
@@ -88,10 +152,7 @@ static void cpy_rect(uint8_t *src, uint16_t src_x, uint16_t src_y,
uint16_t width, uint16_t height,
bool bnd_chk, uint8_t mult, uint8_t div,
bool transp,
- uint32_t transp_key
-
- )
-
+ uint32_t transp_key, bool alpha)
{
// TODO optimize!
for(int x=0;x<width;x++)
@@ -99,15 +160,59 @@ static void cpy_rect(uint8_t *src, uint16_t src_x, uint16_t src_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);
+ // TODO: quick workaround for arrow black
+ if(alpha)
+
+ put_pixel_alpha(dst,dst_x+x,dst_y+y,val);
+ else put_pixel(dst,dst_x+x,dst_y+y,val);
+
}
+}
+
+static void add_icon(char *cmd)
+{
+ strcpy(icons[next_icon].command,cmd);
+ icons[next_icon].posx=next_icon_x;
+ icons[next_icon].posy=next_icon_y;
+ icons[next_icon].active=false;
+ icons[next_icon].width=120;
+ icons[next_icon].height=120;
+
+ icons[next_icon].iconx=next_icon*120+25;
+ icons[next_icon].icony=0;
+ next_icon_x+=130;
+
+ next_icon++;
+}
+
+static void put_icon(uint8_t *dst, struct icon *ico)
+{
+if(ico->active)
+cpy_rect(icon_data,ico->iconx,ico->icony, // from
+ dst, ico->posx,ico->posy, // to
+ ico->width,ico->height, // icon dimensions
+ false,
+ 2, 0, // scaling not implemented yet anyway, not sure how to use them :P
+ true, // transparency color key
+ 0xff00ff // color key of transp
+ ,false
+ );
+else
+cpy_rect(icon_data,ico->iconx,ico->icony, // from
+ dst, ico->posx,ico->posy, // to
+ ico->width,ico->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
+ );
}
-static void put_win(struct window *win)
+static void put_win(uint8_t *dst, struct window *win)
{
+
struct pdirectory* mydir;
x86_cli();// do not reschedule us til ready!
@@ -115,14 +220,24 @@ static void put_win(struct window *win)
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;x<win->posx+win->width;x++)
+ // iterate over invalidated rects
+ while(ringbuffer_has(win->invl))
{
- usery=0;
- for(uint16_t y=win->posy;y<win->posy+win->height;y++)
+ 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)
@@ -141,8 +256,6 @@ static void put_win(struct window *win)
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 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);
@@ -151,16 +264,18 @@ static void put_win(struct window *win)
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(backbuffer,x,y,(user_vmem[userx+usery*640]));
+ put_pixel(dst,x,y,(user_vmem[userx+usery*640]));
}
usery++;
}
userx++;
}
+ }
//if(win->vmem)
//{
x86_set_page_directory(mydir);
@@ -169,25 +284,50 @@ static void put_win(struct window *win)
//draw boundaries
- if(option_win_borders)
+ if(option_win_borders&&win->draw_border)
{
+ win->draw_border=false;
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
+ put_pixel(dst,x,win->posy,0xffffff); //TOP
+ put_pixel(dst,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
+ put_pixel(dst,win->posx,y,0xffffff); //LEFT
+ put_pixel(dst,win->posx+win->width-1,y,0xffffff); //RIGHT
}
}
//
}
+static void put_bg(uint8_t *dst)
+{
+ while(ringbuffer_has(&bg_invl))
+ {
+ int ry=ringbuffer_get(&bg_invl)+256*ringbuffer_get(&bg_invl);
+ int rx=ringbuffer_get(&bg_invl)+256*ringbuffer_get(&bg_invl);
+ int rh=ringbuffer_get(&bg_invl)+256*ringbuffer_get(&bg_invl);
+ int rw=ringbuffer_get(&bg_invl)+256*ringbuffer_get(&bg_invl);
+
+cpy_rect(bgimage,rx,ry, // from
+ dst,rx,ry, // to
+ rw,rh, // 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
+ );
-static void put_mouse()
+ }
+}
+static void put_mouse(uint8_t *dst,bool before)
{
+
+static int last_put_mouse_x=0;
+static int last_put_mouse_y=0;
+
int iconx=mouse_icon_lx;
int icony=mouse_icon_ly;
@@ -197,13 +337,31 @@ if(mouse_k&1)
icony=mouse_icon_active_ly;
}
-cpy_rect(icons,iconx,icony, // from
- backbuffer, mouse_x,mouse_y, // to
+if(before)
+{
+cpy_rect(bgimage,last_put_mouse_x,last_put_mouse_y, // from
+ dst, last_put_mouse_x,last_put_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
+ false, // transparency color key
0xffffff // color key of transp
+ ,false
+ );
+return;
+}
+
+last_put_mouse_x=mouse_x;
+last_put_mouse_y=mouse_y;
+
+cpy_rect(icon_data,iconx,icony, // from
+ dst, 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
+ 0xff00ff // color key of transp
+ ,false
);
}
@@ -224,7 +382,7 @@ void compositor_del_window(uint32_t addr)
}
}
-void compositor_add_window(uint32_t addr,uint32_t pid)
+void compositor_add_window(uint32_t addr,uint32_t pid,ringbuffer *r)
{
klog("window added");
if (next_window>=MAX_WINDOWS)kpanic("max number of windows reached. increase MAX_WINDOWS");
@@ -238,12 +396,14 @@ void compositor_add_window(uint32_t addr,uint32_t pid)
next_y+=100;
windows[0].width=640;
- windows[0].height=480;
+ windows[0].height=400;
- windows[0].color=0xAAAA00AA;
windows[0].active=0;
windows[0].vmem=addr;
windows[0].pid=pid;
+ windows[0].invl=r;
+ windows[0].draw_border=true;
+ windows[0].draw_meat=true;
next_window++;
compositor_mouse_handle(200,200,0);
@@ -252,15 +412,27 @@ void compositor_add_window(uint32_t addr,uint32_t pid)
// TODO : TEXTMODE FALLBACK!
void compositor_init(uint16_t width, uint16_t height, uint16_t depth, uint16_t pitch)
{
+ bg_invl=ringbuffer_init(3);
+
vesa_width=width;
vesa_height=height;
vesa_depth=depth/8;
vesa_pitch=pitch;
+ int icon_count=5;
+ next_icon_x=width/2-icon_count*130/2;
+ next_icon_y=height-130;
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");
+
+ add_icon("vim");
+ add_icon("vim");
+ add_icon("vim");
+ add_icon("vim");
+ add_icon("vim");
+ add_icon("vim");
}
void compositor_wake()
@@ -274,27 +446,49 @@ void compositor_wake2()
void compositor_swap_buffers()
{
- if(skip_render||skip_render2)return;
+ //if(skip_render||skip_render2)return;
+ if(skip_render2)return; // force rate
+
skip_render=true;
skip_render2=true;
+ static frames=0;
+ static uint64_t last=0;
+ if(!last)last=timer_get_ms();
+ uint64_t now=timer_get_ms();
+ frames++;
+ if(now-last>3000)
+ {
+ klog("fps: %d",frames*1000/(now-last));
+
+ last=now;
+ frames=0;
+ }
+
+
+
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);
+ if(first)memcpy(VMEM_FRAMEBUFFER,bgimage,vesa_pitch*vesa_height);// TODO optimize? rects only too??
+ first=false;
+ put_bg(VMEM_FRAMEBUFFER);
+
+ put_mouse(VMEM_FRAMEBUFFER,true);
+
for(int i=next_window-1;i>=0;i--)
{
- put_win(&windows[i]);
+ put_win(VMEM_FRAMEBUFFER,&windows[i]);
}
- put_mouse();
+ for(int i=next_icon-1;i>=0;i--)
+ {
+ // put_icon(backbuffer,&icons[i]);
+ }
+
+ put_mouse(VMEM_FRAMEBUFFER,false);
// TODO optimize? rects only too?
- memcpy(VMEM_FRAMEBUFFER,backbuffer,vesa_height*vesa_width*vesa_depth);
- first=false;
+// memcpy(VMEM_FRAMEBUFFER,backbuffer,vesa_pitch*vesa_height);
}
void compositor_kb_handle(char c)
@@ -310,9 +504,12 @@ void compositor_kb_handle(char c)
}
}
+// TODO: check what is active ONLY on refresh screen!
void compositor_mouse_handle(int16_t diff_x,int16_t diff_y, uint8_t key)
{
// klog("%d %d %d",diff_x,diff_y,key);
+ static uint8_t lastkey;
+
mouse_x+=diff_x;
mouse_y+=diff_y;
mouse_k=key;
@@ -330,14 +527,62 @@ void compositor_mouse_handle(int16_t diff_x,int16_t diff_y, uint8_t key)
}
int active=-1;
- for(int i=0;i<MAX_WINDOWS;i++)
+ bool active_win=false;
+
+ for(int i=0;i<next_icon;i++)
{
+ struct icon *w=&icons[i];
+ 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->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>=vesa_width)w->posx=vesa_width-640;
+ if(w->posy+w->height>=vesa_height)w->posy=vesa_height-480;
+ */
+ }
+
+ w->active=true;
+ active=i;
+ }
+ else
+ {
+ w->active=false;
+ }
+ }
+
+ for(int i=0;i<next_window;i++)
+ {
struct window *w=&windows[i];
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;
@@ -349,24 +594,51 @@ void compositor_mouse_handle(int16_t diff_x,int16_t diff_y, uint8_t key)
if(w->posx+w->width>=vesa_width)w->posx=vesa_width-640;
if(w->posy+w->height>=vesa_height)w->posy=vesa_height-480;
+ w->draw_border=true;
+
+ }
+ else
+ {
+ w->draw_meat=true;
+ if(lastkey&1)
+ {
+ 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;
active=i;
}
else
{
+
+
w->active=false;
}
}
- if(active!=-1&&active!=0&&(key&1))
+ if(active_win&&active!=-1&&active!=0&&(key&1))
{
struct window temp;
temp=windows[active];
windows[active]=windows[0];
windows[0]=temp;
}
+
+ lastkey=key;
}
// load background image or generate one if (param == 0)
@@ -389,7 +661,7 @@ void compositor_set_background(char *ppm_raw_filename)
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);
+ put_pixel(icon_data,x,y,val);
i++;
}
}
@@ -405,12 +677,17 @@ void compositor_set_background(char *ppm_raw_filename)
{
for(int y=0;y<vesa_height;y++)
{
+ uint32_t val;
+ if(y%2)
+ {
int diffx=center_x-x;
int diffy=center_y-y;
int dist=diffx*diffx+diffy*diffy;
- int val = 0xff*dist/max_dist;
+ val = 0xaa*dist/max_dist;
+ }
+ else val=0x0;
- put_pixel(backbuffer,x,y,val);
+ put_pixel(bgimage,x,y,val<<8);
}
}
}