讀書筆記《30天自制操作系統》day10

1. 顯示到屏幕上的圖形界面信息要分層,比如最頂層是鼠標,中間是應用程序,最低是桌面。

2. 移動鼠標和窗口應用可以看爲是移動圖層。

3. 屏幕顯示的原理是向顯存內寫信息,顯存的地址在0x000a0000這個已經在前面見過了。

/*一個圖層結構體*/
struct SHEET
{
    unsigned char* buf;/*圖層內容地址*/
    int bxsize,bysize;/*圖層大小*/
    int vx0,vy0;/*圖層在屏幕上位置*/
    int col_inv;/*色號(調色板)*/
    int height;/*圖層高度*/
    int flag;/*設定信息*/
};
/*管理多個圖層結構體*/
#define MAX_SHEETS 256
struct SHTCTL
{
    unsigned char *vram;/*VRAM地址*/
    int xsize,ysize;/*屏幕寬高*/
    int top;/*最上圖層高度*/
    struct SHEET * sheets[MAX_SHEETS];/*下面的圖層信息混亂,所以按照高度進行排序*/
    struct SHEET sheets0[MAX_SHEETS];/*保存所有圖層信息*/
};

4. 內存空間的分配應使用前面學過的知識,不使用static分配,初始化圖層管理節點,一次性分配足夠大的管理空間

#define SHEET_USE		1

struct SHTCTL *shtctl_init(struct MEMMAN *memman, unsigned char *vram, int xsize, int ysize)
{
	struct SHTCTL *ctl;
	int i;
	ctl = (struct SHTCTL *) memman_alloc_4k(memman, sizeof (struct SHTCTL));
	if (ctl == 0) {
		goto err;
	}
	ctl->vram = vram;
	ctl->xsize = xsize;
	ctl->ysize = ysize;
	ctl->top = -1; 
	for (i = 0; i < MAX_SHEETS; i++) {
		ctl->sheets0[i].flags = 0;
	}
err:
	return ctl;
}

5. 生成未使用的圖層,從已經分配管理圖層中找到一個空閒的標記佔用

struct SHEET *sheet_alloc(struct SHTCTL *ctl)
{
	struct SHEET *sht;
	int i;
	for (i = 0; i < MAX_SHEETS; i++) {
		if (ctl->sheets0[i].flags == 0) {
			sht = &ctl->sheets0[i];
			sht->flags = SHEET_USE; 
			sht->height = -1; 
			return sht;
		}
	}
	return 0;	
}

6. 設置圖層,指定圖層顯示緩存區及其大小等

void sheet_setbuf(struct SHEET *sht, unsigned char *buf, int xsize, int ysize, int col_inv)
{
	sht->buf = buf;
	sht->bxsize = xsize;
	sht->bysize = ysize;
	sht->col_inv = col_inv;
	return;
}

7. 設定某個圖層的高度

void sheet_updown(struct SHTCTL *ctl, struct SHEET *sht, int height)
{
	int h, old = sht->height; 
        /*修正高度*/
	if (height > ctl->top + 1) {
		height = ctl->top + 1;
	}
	if (height < -1) {
		height = -1;
	}
	sht->height = height;
        /*對sheets重新排列,線性數組的前後移動操作,不難*/
	if (old > height) {	
		if (height >= 0) {
			for (h = old; h > height; h--) {
				ctl->sheets[h] = ctl->sheets[h - 1];
				ctl->sheets[h]->height = h;
			}
			ctl->sheets[height] = sht;
		} else {
			if (ctl->top > old) {
				for (h = old; h < ctl->top; h++) {
					ctl->sheets[h] = ctl->sheets[h + 1];
					ctl->sheets[h]->height = h;
				}
			}
			ctl->top--;
		}
		sheet_refresh(ctl); 
	} else if (old < height) {
		if (old >= 0) {
			
			for (h = old; h < height; h++) {
				ctl->sheets[h] = ctl->sheets[h + 1];
				ctl->sheets[h]->height = h;
			}
			ctl->sheets[height] = sht;
		} else {	
			for (h = ctl->top; h >= height; h--) {
				ctl->sheets[h + 1] = ctl->sheets[h];
				ctl->sheets[h + 1]->height = h + 1;
			}
			ctl->sheets[height] = sht;
			ctl->top++; 
		}
		sheet_refresh(ctl); 
	}
	return;
}

8. 刷新各圖層,寫入顯存,這個需要優化

void sheet_refresh(struct SHTCTL *ctl)
{
	int h, bx, by, vx, vy;
	unsigned char *buf, c, *vram = ctl->vram;
	struct SHEET *sht;
	for (h = 0; h <= ctl->top; h++) {
		sht = ctl->sheets[h];
		buf = sht->buf;
		for (by = 0; by < sht->bysize; by++) {
			vy = sht->vy0 + by;
			for (bx = 0; bx < sht->bxsize; bx++) {
				vx = sht->vx0 + bx;
				c = buf[by * sht->bxsize + bx];
				if (c != sht->col_inv) {
					vram[vy * ctl->xsize + vx] = c;
				}
			}
		}
	}
	return;
}

9. 移動圖層

void sheet_slide(struct SHTCTL *ctl, struct SHEET *sht, int vx0, int vy0)
{
	sht->vx0 = vx0;
	sht->vy0 = vy0;
	if (sht->height >= 0) { 
		sheet_refresh(ctl); 
	}
	return;
}

10. 釋放圖層

void sheet_free(struct SHTCTL* ctl,struct SHEET* sht)
{
    if(sht->height>=0)
    {
        sheet_updown(ctl,sht,-1);
    }
    sht->flags=0;
    return ;
}

11.優化略(計算得到圖層交叉部分重繪,其它不用繪)
 


 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章