30天自制操作系统:第十天 叠加处理

2021年9月21日 7点热度 0条评论 来源: nepu_bin

1 内存管理(续)(harib07a)

memman_allocmemman_free 函数能够以1字节为单位进行内存管理,这种方式虽然不错,但是有一点不足:在反复进行内存分配和内存释放之后,内存中就会出现很多不连续的小段未使用空间,这样就会把man->frees(该属性指示了空闲空间块的总个数)消耗殆尽。

因此,作者编写了一些总是以0x1000字节为单位进行内存分配和释放的函数,它们会把指定的内存大小按0x1000字节(4KB)为单位向上舍入,选择0x1000这个数值非常精妙,我们慢慢来理解这个“精妙之处”。

刚看程序,有点懵,但是后面作者给出了对向上向下取整详细的解释:



这里都是作者解释如何完成向上向下取整的操作,非常通俗易懂。

拓展阅读

作者深度解释了使用0x1000字节作为单位的高明之处。

2 叠加处理(harib07b)

之后的这几个小节中包含了非常多的程序代码,笔者就给出一些理解吧,刚学确实有点懵懂。


结构体中的内容比较多,首先 SHEET 表示“透明图层”的意思。

  • buf用来记录图层上所描画内容的地址(buffer)
  • bxsize * bysize可以表示图层的整体大小
  • vx0、vy0是表示图层在画面上的位置坐标(v是VRAM的略语)
  • col_inv表示透明色色号,它是 color(颜色) 和 invisible(透明)的组合略语
  • height 表示图层高度
  • flags用于存放有关图层的各种设定信息

只有一个图层是不能实现叠加处理的,所以必须创建一个管理多重图层信息的结构。


结构体SHTCTL(sheet control,图层管理):

  • MAX_SHEETS是能够管理的最大图层数,这里设置为256
  • vram、xsize、ysize代表VRAM的地址和画面的大小,每次从BOOTINFO查询太麻烦了,在这里预先对它们进行赋值操作。
  • top表示最上面图层的高度
  • sheet0这个结构体数组用于存放我们准备的256个图层的信息
  • sheets是用于记录地址变量的一个指针数组(类型为struct SHEET,可以写成 (struct SHEET*) sheets[ MAX_SHEETS ]; ),作用:由于sheets0中的图层顺序混乱,所以将它们按照高度进行升序排序,然后将地址写入到sheets中,这样就方便多了。
    理解SHTCTL结构体中的内容:

    接下来就是程序部分了。

    程序做了些什么?
    首先使用 memman_alloc_4k来分配用于记忆图层控制变量的内存空间,这时必须指定该变量所占空间的大小,不过可以使用 sizeof运算符,让编译器自动计算。接着,给控制变量赋值,给其下的所有图层变量都加上“未使用”标签。

sheet_alloc函数

函数对所有图层进行遍历,找出第一个 flags 等于 0(未使用) 的图层,将其标记更改为 “正在使用”,设置 height 属性为 - 1, 表示隐藏,最后再返回这个图层的地址即可;如果没有找到符合条件(未使用)的图层,那么返回0表示所有的SHEET都处于正在使用的状态

设定图层内容的sheet_setbuf函数


用于设定图层的缓冲区大小和透明色的函数,函数中只完成了一些简单的赋值。

设定底板高度的 sheet_updown函数


程序中包含了比较多的注释,只能慢慢看程序一次又一次去理解了。

从下往上描述图层的sheet_refresh函数


对于已经设定了高度的所有图层而言,要从下往上,将透明以外的所有像素都恢复到VRAM中。由于是从下开始复制,所以最后最上面的内容就留在了画面上。

sheet_slide函数


不改变图层高度而只上下左右移动图层的函数。

释放已使用图层内存的sheet_free函数

HariMain函数



主函数负责调用这些函数完成实际功能,这部分需要仔细琢磨。
这里有两个图层,分别是sht_backsht_mouse,还准备了两个缓冲区buf_backbuf_mouse,用于在其中描绘图形,以前我们指定为 binfo->vram的部分,现在有很多都改成了 buf_back。而且每次修改缓冲区之后都要刷新。

3 提高叠加处理速度(1)(harib07c)

鼠标指针虽然最多只有16 x 16 = 256个像素,但是上一章节里卖的程序,只要它稍一移动,程序就会对整个画面进行刷新,也就是重新绘制320 x 200 = 64000个像素。而实际上,只重新描绘移动相关的部分,也就是移动前后的部分就可以了,即 256 x 2 = 512个像素,这只是原来64000像素的0.8%而已,根据这个思路改写一下程序。

sheet.c节选


函数几乎和sheet_refresh一样,唯一的不同点在于它能使用vx0 ~ vy1指定刷新的范围,而我们之追加了一个if语句就实现了这个新功能。

现在用这个 refreshsub函数来提高sheet_slide的运行速度。


这段程序所做的是:首先记住移动前的显示位置,再设定新的显示位置,最后只需要重新描绘移动前和移动后的地方就可以了。

移动鼠标的时候,由于要在画面上显示坐标等信息,结果又执行了sheet_refresh程序,所以还是很慢, 必须解决一下图层内文字显示的问题。
这里所说的在图层上显示文字,实际上不是改写图层的全部内容,假设我们写了20个字,那么8 x 16 x 20 = 2560,也就仅仅重写2560个像素的内容就足够了,但现在每次都要重写64000个像素的内容,所以速度才会那么慢。

所谓指定范围,并不是直接指定画面内的坐标,而是以缓冲区的坐标来表示。这样一来,HariMain就可以 不考虑图层在画面中的位置了。

4 提高叠加处理速度(2)(harib07d)





感受

中秋节快乐呀,今天的内容看的还是有点懵懂,大体上好似明白,但是一旦细节一点的内容有点绕不过去,现在的窘境就是函数太多了,有些地方没有完全吃透,有一些小疑问还需要解决(这些必须慢慢理解慢慢消化)。已经第十天了,每天一篇博客确实挺耗费时间的,相比做其他实验做OS当然没那么快乐,希望能熬过去,加油

    原文作者:nepu_bin
    原文地址: https://blog.csdn.net/Genius_bin/article/details/120400009
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系管理员进行删除。