文章出處

《30天自制操作系統》筆記(08)——疊加窗口刷新

進度回顧

上一篇中介紹了內存管理的思路和算法,我們已經可以動態申請和釋放內存了。這不就是(Heap)么。在此基礎上,本篇要做一段程序,一并解決窗口和鼠標的疊加處理問題。

問題

在之前的《《30天自制操作系統》筆記(05)——啟用鼠標鍵盤》篇,已經能夠移動鼠標了。但是遺留了如下圖所示的一個小問題。

我們希望的情形是這樣的:

實際上,當前版本的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下我測試的時候根本沒有差別,未優化的版本也不卡)

有了本篇的準備,下一步就可以制作和顯示窗口了。

請查看下一篇《《30天自制操作系統》筆記(09)——繪制窗口》


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()