博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《30天自制操作系统》笔记(08)——叠加窗口刷新
阅读量:5260 次
发布时间:2019-06-14

本文共 4005 字,大约阅读时间需要 13 分钟。

《30天自制操作系统》笔记(08)——叠加窗口刷新

进度回顾

中介绍了内存管理的思路和算法,我们已经可以动态申请和释放内存了。这不就是(Heap)么。在此基础上,本篇要做一段程序,一并解决窗口和鼠标的叠加处理问题。

问题

在之前的篇,已经能够移动鼠标了。但是遗留了如下图所示的一个小问题。

我们希望的情形是这样的:

实际上,当前版本的OS还没有窗口图层的东西。本篇要做一段程序,一并解决窗口和鼠标的叠加处理问题。

在屏幕上显示多个窗口,类似于photoshop中显示多个图层。从桌面壁纸到每个窗口(层)到最上层的鼠标(鼠标也视为一个小窗口),将绘制了图案的透明图层叠加起来。

最初版解决方案

首先定义图层的数据结构。

1 #define MAX_SHEETS        256 2 struct SHEET { 3     unsigned char *buf; 4     int bxsize, bysize, vx0, vy0, col_inv, height, flags; 5 }; 6 struct SHTCTL { 7     unsigned char *vram; 8     int xsize, ysize, top; 9     struct SHEET *sheets[MAX_SHEETS];10     struct SHEET sheets0[MAX_SHEETS];11 };

原作者用sheet表示图层,看来英文很一般,用 layer似乎更恰当。

图层层次变更(当前窗口变更)、图层位置移动(窗口位置移动)这些代码实在没什么可说。刷新函数也很简单,就是从下(桌面壁纸)往上(鼠标),将透明以外的所有像素复制到VRAM中。代码如下。

1 void sheet_refresh(struct SHTCTL *ctl) 2 { 3     int h, bx, by, vx, vy; 4     unsigned char *buf, c, *vram = ctl->vram; 5     struct SHEET *sht; 6     for (h = 0; h <= ctl->top; h++) { 7         sht = ctl->sheets[h]; 8         buf = sht->buf; 9         for (by = 0; by < sht->bysize; by++) {10             vy = sht->vy0 + by;11             for (bx = 0; bx < sht->bxsize; bx++) {12                 vx = sht->vx0 + bx;13                 c = buf[by * sht->bxsize + bx];14                 if (c != sht->col_inv) {15                     vram[vy * ctl->xsize + vx] = c;16                 }17             }18         }19     }20     return;21 }

很明显这样太没效率了。下面就对刷新功能进行优化。

优化1-移动优化

鼠标层只有16*16=256个像素。但是根据上文的代码,只要鼠标稍微动一下,OS就要重绘320*200=64000个像素。这是不必要的。只需重绘移动前后的部分即256*2=512个像素就可了。512只是64000的0.8%。以后启用高分辨率了,性能提升会更多。

1 void sheet_refreshsub(struct SHTCTL *ctl, int vx0, int vy0, int vx1, int vy1) 2 { 3     int h, bx, by, vx, vy; 4     unsigned char *buf, c, *vram = ctl->vram; 5     struct SHEET *sht; 6     for (h = 0; h <= ctl->top; h++) { 7         sht = ctl->sheets[h]; 8         buf = sht->buf; 9         for (by = 0; by < sht->bysize; by++) {10             vy = sht->vy0 + by;11             for (bx = 0; bx < sht->bxsize; bx++) {12                 vx = sht->vx0 + bx;13                 if (vx0 <= vx && vx < vx1 && vy0 <= vy && vy < vy1) {14                     c = buf[by * sht->bxsize + bx];15                     if (c != sht->col_inv) {16                         vram[vy * ctl->xsize + vx] = c;17                     }18                 }19             }20         }21     }22     return;23 }

窗口(鼠标)移动时,只需先调用此函数重绘移动前的部分,再调用此函数重绘移动后的部分就行了。

优化2-文字优化

移动鼠标时,由于要在桌面上显示坐标等信息,又被迫重绘了整个桌面,所以还是很慢。下面来优化这个瓶颈。

原理和优化1是一样的。只重绘文字所在的部分就行了。不再赘述。

优化3-减少判定

在上文的"sheet_refreshsub"函数中,使用了长长的"if (vx0 <= vx && vx < vx1 && vy0 <= vy && vy < vy1)"判定。但对于窗口外(即透明色)的位置,根本不用重绘,所以这个判定也就不需要了。我们就把这一点优化一下,只更新窗口所在的矩形范围内的地方。

1 void sheet_refreshsub(struct SHTCTL *ctl, int vx0, int vy0, int vx1, int vy1) 2 { 3     int h, bx, by, vx, vy, bx0, by0, bx1, by1; 4     unsigned char *buf, c, *vram = ctl->vram; 5     struct SHEET *sht; 6     for (h = 0; h <= ctl->top; h++) { 7         sht = ctl->sheets[h]; 8         buf = sht->buf; 9         /* 使用vx0~vy1,对bx0~by1进行倒推*/10         bx0 = vx0 - sht->vx0;11         by0 = vy0 - sht->vy0;12         bx1 = vx1 - sht->vx0;13         by1 = vy1 - sht->vy0;14         if (bx0 < 0) { bx0 = 0; }15         if (by0 < 0) { by0 = 0; }16         if (bx1 > sht->bxsize) { bx1 = sht->bxsize; }17         if (by1 > sht->bysize) { by1 = sht->bysize; }18         for (by = by0; by < by1; by++) {19             vy = sht->vy0 + by;20             for (bx = bx0; bx < bx1; bx++) {21                 vx = sht->vx0 + bx;22                 c = buf[by * sht->bxsize + bx];23                 if (c != sht->col_inv) {24                     vram[vy * ctl->xsize + vx] = c;25                 }26             }27         }28     }29     return;30 }

说实话原作者的变量命名还是有点晦涩。理解原理就可以了,代码不需费劲看,因为真的很简单。

总结

本篇虽然没有在桌面上画出类似windows应用程序窗口那样的窗口,但是已经为其准备好了重绘的数据结构和算法。而且对算法进行优化,虽然优化原理及其简单(缩小不必要的重绘范围),但是效果很好。话是这么说,这个优化效果就没办法用图片展示了,自己在本地分别运行一下优化前后的版本吧还是。(建议用VMware,这个能看到很明显的差别,在QEMU下我测试的时候根本没有差别,未优化的版本也不卡)

有了本篇的准备,下一步就可以制作和显示窗口了。

转载于:https://www.cnblogs.com/bitzhuwei/p/OS-in-30-days-08-refresh-windows.html

你可能感兴趣的文章
Redmine
查看>>
帧的最小长度 CSMA/CD
查看>>
树状数组及其他特别简单的扩展
查看>>
普通求素数和线性筛素数
查看>>
PHP截取中英文混合字符
查看>>
【洛谷P1816 忠诚】线段树
查看>>
电子眼抓拍大解密
查看>>
poj 1331 Multiply
查看>>
tomcat7的数据库连接池tomcatjdbc的25个优势
查看>>
Html 小插件5 百度搜索代码2
查看>>
Ubuntu(虚拟机)下安装Qt5.5.1
查看>>
java.io.IOException: read failed, socket might closed or timeout, read ret: -1
查看>>
java 常用命令
查看>>
卷积中的参数
查看>>
51nod1076 (边双连通)
查看>>
Item 9: Avoid Conversion Operators in Your APIs(Effective C#)
查看>>
深入浅出JavaScript(2)—ECMAScript
查看>>
ViewPager的onPageChangeListener里面的一些方法参数:
查看>>
Jenkins关闭、重启,Jenkins服务的启动、停止方法。
查看>>
CF E2 - Array and Segments (Hard version) (线段树)
查看>>