发布于 

30天自制操作系统(10)

DAY10_叠加处理

1.内存管理(续)

  • memory.c中增加了“向上舍入”的部分,即我们要编写一些总是以0x1000字节为单位进行内存分配和释放的函数,它们会把指定的内存大小按0x1000字节为单位向上舍入( roundup)。
  • 从向下舍入开始
    要想把十六进制的某一位设置为0,同样只进行“与运算”就可以。
  • 向上舍入:先向下舍入,再在它的结果上做个加法运算就可以了。(要先判断后几位是不是0)
  • 更好的向上舍入的方法:i = (i + 0xfff) & 0xfffff000;

2.叠加处理

  • 寻找一种方法,不仅适用于鼠标的叠加,还适用于窗口的叠加。
  • 在程序中创建管理多重图层信息的结构SHTCTL
  • sheet_refresh函数:这个函数会从下到上描绘所有的图层。refresh是“刷新”的意思。电视屏幕就是在1秒内完成多帧的描绘才做出动画效果的,这个动作就被称为刷新。而这种对图层的刷新动作,与电视屏幕的动作有些相似,所以我们也给它起名字叫做刷新。
  • sheet_slide:不改变图层的高度而只上下左右移动图层的函数。
  • sheet_free释放已使用图层的内存的函数。
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; /*一个SHEET没都有 */
for (i = 0; i < MAX_SHEETS; i++) {
ctl->sheets0[i].flags = 0; /* 标记为未使用 */
}
err:
return ctl;
}

首先使用memman_alloc_4k来分配用于记忆图层控制变量的内存空间,这时必须指定该变量所占空间的大小,不过我们可以使用sizeof(struct SHTCTL)这种写法,让C编译器自动计算。只要写sizeof(变量型),C编译器就会计算出该变量型所需的字节数。
接着,我们给控制变量赋值,给其下的所有图层变量都加上“未使用”标签。

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

  • 只需要重新描绘鼠标移动相关的部分,也就是移动前后的部分就可以了,即256×2=512个像素。这只是64 000像素的0.8%而已,所以有望提速很多。现在我们根据这个思路写一下程序。
  • 要在画面上显示坐标等信息,结果又执行了sheet_refresh程序。所以我们要解决图层内文字显示的问题。

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

  • 使不写入像素内容,也要多次执行if语句。我们最初就应该把for语句的范围限定在刷新范围之内。
    void sheet_refreshsub(struct SHTCTL *ctl, int vx0, int vy0, int vx1, int vy1) 
    {
    int h, bx, by, vx, vy, bx0, by0, bx1, by1;
    unsigned char *buf, c, *vram = ctl->vram;
    struct SHEET *sht;
    for (h = 0; h <= ctl->top; h++) {
    sht = ctl->sheets[h];
    buf = sht->buf;
    /* 使用vx0~vy1,对bx0~by1进行倒推 */
    bx0 = vx0 - sht->vx0;
    by0 = vy0 - sht->vy0;
    bx1 = vx1 - sht->vx0;
    by1 = vy1 - sht->vy0;
    if (bx0 < 0) { bx0 = 0; } /* 说明(1) */
    if (by0 < 0) { by0 = 0; }
    if (bx1 > sht->bxsize) { bx1 = sht->bxsize; } /* 说明(2) */
    if (by1 > sht->bysize) { by1 = sht->bysize; }
    for (by = by0; by < by1; by++) {
    vy = sht->vy0 + by;
    for (bx = bx0; bx < bx1; bx++) {
    vx = sht->vx0 + bx;
    c = buf[by * sht->bxsize + bx];
    if (c != sht->col_inv) {
    vram[vy * ctl->xsize + vx] = c;
    }
    }
    }
    }
    return;
    }