为了将字符显示到显示器上,通常需要一种硬件的支持,这种硬件就是显卡。显卡的主要作用是控制显示器的显示模式和状态,并将内容显示到显示器上。显卡控制显示器的最小单位是像素,一个像素对应显示器上的一个点。为了控制像素的显示,在显卡上通常有一个按字节访问的存储器—显示存储器(Video RAM,简称显存)。将需要显示的内容预先写入显存中,显卡会周期性地把内容从显存显示到显示器上。
显卡支持的显示模式通常有两类:字符模式(Character Mode)和图形模式(Graphics Mode)。MaQueOS使用的显示模式为图形模式。在MaQueOS中,显示参数被定义为宏。MaQueOS显示参数的定义见代码清单1.1。
代码清单1.1 MaQueOS的显示参数
如图1.1所示,显示器的分辨率为1280(NR_PIX_X)×800(NR_PIX_Y),像素总数为1280×800=1024000。每个字符由8(CHAR_WIDTH)×16(CHAR_HEIGHT)的像素点阵组成,这个像素点阵被称为字模(Fonts)。显示器每行可显示160(1280÷8)个字符,总共可显示50(800÷16)行。
在显示器驱动程序中,write_char函数(详见代码清单1.2)用于将指定的字符写入显存中指定的位置。write_char函数有3个参数,第1个参数为字符的ASCII值,第2个和第3个参数为字符显示位置的坐标。本节以显示字符“!”为例,分析write_char函数的处理过程,其中字符的显示位置为第2行第4列。
图1.1 MaQueOS显示参数
代码清单1.2 write_char函数
下面对代码清单1.2进行说明。
在 第13行 中,如上节所述,每个字符对应一个8×16像素点阵的字模,“!”的字模如图1.2所示。其中,值为1的比特组成一个形状为!的图形。MaQueOS在显示器上支持显示的字符个数为95。这些可显示字符对应的字模存放在font.c文件的fonts数组中。如图1.2所示,每个字模需要16字节来表示,即在fonts数组中占用16项,因此,fonts数组中偏移为0的字模占用第0~15项,对应字符的ASCII值为32(空格),偏移为1的字模占用第16~31项,对应字符的ASCII值为33(“!”),以此类推,偏移为94的字模占用最后16项,对应字符的ASCII值为126(“~”)。
图1.2 字符“!”的字模
因为fonts数组中偏移为0的字模的对应字符的ASCII值为32,所以,为了获取字符的对应字模在fonts数组中的起始项(共16项),应先将字符的ASCII值减去32得到该字符的对应字模在fonts数组中的偏移,再乘以每个字模占用的字节数16,最终得到该字符的对应字模在fonts数组中的起始项。字符“!”的ASCII值为33,因此,对应字模在fonts数组中的偏移为1,再乘以每个字模占用字节数16,最终计算出该字模在fonts数组中的起始项为16。
在 第14行 中,获取字符的起始像素在显存中的起始地址,计算过程如下:
1)计算出字符起始像素在显示器中的偏移量。如图1.1所示,因为一行字符占16行像素,所以第yy行字符前共有yy×16行像素。即,第yy行字符前像素的总数为yy×16×1280。又因为一列字符占8列像素,所以第xx列字符前共有xx×8列像素。若将字符“!”显示在显示器中的第2行第4列,因为第2行字符前像素的总数为2×16×1280=40960,并且在第2×16行像素中,第4列字符前像素的总数为4×8=32,所以字符“!”的起始像素在显示器上的偏移为40960+32=40992。
2)每个像素在显存中占4字节(NR_BYTE_PIX),其中前3字节分别代表B、G、R,决定了该像素的颜色。因此将步骤1中的计算结果乘以4,得到字符的起始像素在显存中的偏移。最后,将该偏移加上显存起始地址0x40000000(VRAM_BASE),得到字符的起始像素在显存中的起始地址。
在 第15~30行 中,按行循环遍历字模,共遍历16字节。在 第29行 中,每行遍历结束后,需要重新计算字符的下一行像素的起始像素在显存中的起始地址。需要增加的字节数为(1280-8)×4,其中,1280-8表示显示器一行像素的总数(1280)减去字符一行像素的数量(8),4表示每个像素在显存中占用的字节数(结果为5088)。
对于 第17~28行 代码,在每行中,按列循环遍历字模,共遍历每个字节中的8位。其中,在 第19~25行 中,若字模中的当前位为1,则将对应像素在显存中的(B,G,R)对应的字节分别设置为(0,0,255),表示将该像素绘制为红色。在 第26~27行 中,若字模中的当前位为0,则直接跳过该位对应像素在显存中占用的4个字节。
如图1.2所示,当遍历至字符“!”对应字模的第0行第0列时,因为该位的值为0,所以不对像素进行绘制,直接跳过该位对应像素在显存中占用的4个字节。直至遍历到第2行第3列时,因为该位的值为1,所以将该位对应的像素绘制为红色。最终,当字模中的位全部遍历完成后,红色的字符“!”便显示在显示器上。