图层叠加优化
1.简介
在前几节 我们使用窗体图层叠加技术 解决了窗体鼠标移动时 破坏其他窗体界面的问题
但同时 也引入了新的问题
当鼠标移动时 内核会将所有窗口重新绘制
如果当前系统打开的窗口很多 假设有几十上百个
那么鼠标动一下 就重新绘制上百个窗口
这对cpu资源的消耗就会非常大 整个系统的性能就会被拖垮
由此 我们需要优化内核对窗口更新重绘的设计 降低不必要的损耗
解决方案
我们现在的鼠标 占据的窗口大小是16x16 也就是256个像素
按照现在内核的重绘机制 只要鼠标稍微移动一下 就需要对整个画面进行刷新
也就是重新绘制320x200 = 64000 个像素点
其实只要重新绘制鼠标移动的相关区域就可以了
例如 鼠标从原来坐标点(0,0) 移动到坐标点(1,1)
那么内核只要重绘区域[(0,0), (16,16)] 和 [(1,1), (17,17)] 即可
2.代码
为此 新添加了一个绘制函数
void sheet_refreshsub(struct SHTCTL *ctl, int vx0, int vy0, int vx1, int vy1) { 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; if (vx0 <= vx && vx < vx1 && vy0 <= vy && vy < vy1) { c = buf[by * sht->bxsize + bx]; if (c != sht->col_inv) { vram[vy * ctl->xsize + vx] = c; } } } } } }
这个函数功能就只对每个窗体绘制局部区域 该区域的左上角是(vx0,vy0),右下角是(vx1, vy1)
接着我们改进一下原来的sheet_silde函数 这个函数意义在于窗口移动后重新绘制
现在我们把它改成刷新窗口移动前后所占据的两个区域既可:
void sheet_slide(struct SHTCTL *ctl, struct SHEET *sht, int vx0, int vy0) { int old_vx0 = sht->vx0, old_vy0 = sht->vy0; sht->vx0 = vx0; sht->vy0 = vy0; if (sht->height >= 0) { sheet_refreshsub(ctl, old_vx0, old_vy0, old_vx0 + sht->bxsize, old_vy0 + sht->bysize); sheet_refreshsub(ctl, vx0, vy0, vx0+sht->bxsize, vy0+sht->bysize); } }
第一次调用sheet_refreshsub 为的是刷新窗体移动前的区域
第二次调用sheet_refreshsub 是根据窗体移动后的坐标 重新绘制窗体
还有一处需要改进的是文字的显示
原来我们显示文字时 同样是需要把所有窗口重新绘制一次
还有就是我们的文章只能绘制在桌面背景上
现在我们有了图层的概念 因此我们可以把文字显示机制改进一下
(1)改进一是只对文章所占据的区域进行刷新
(2)改进二是文字可以绘制到给定的图层上 这样文章就可以绘制到指定的窗体 而不再只限制于桌面
代码如下
void showString(struct SHTCTL *shtctl ,struct SHEET *sht, int x, int y, char color, unsigned char *s ) { int begin = x; for (; *s != 0x00; s++) { showFont8(sht->buf, sht->bxsize, x, y,color, systemFont+ *s * 16); x += 8; } sheet_refresh(shtctl, sht, begin, y, x , y + 16); }
输入参数中的sht对应要绘制字符串的窗口图层
调用的sheet_refresh目的就是仅仅更新文字所占据的区域
有了上面的改进后 虽然我们的系统在外在表现上 没有明显的变化
但实际上 性能已经有了上千倍的提升
3.编译运行
我们已经有了打包工具 所以现在打包要简单的多
直接make
接着java
记得
Process process = Runtime.getRuntime().exec("/usr/local/bin/nasm -o kernel.bat kernel.asm"); readProcessOutput(process);
最后img装载运行