在基于帧缓冲的控制台中呈现字符的最快方法是什么?我正在使用 XNU 发行版中的iso_font.h字体。

现在,我正在使用此代码来渲染角色,但它似乎并不太有效:

px = px* ISO_CHAR_WIDTH;
py = py* (ISO_CHAR_HEIGHT-1);

for (int i = 0; i < 15; i += 1)
{
    int sym = iso_font[c*16+i];

    int x = px;
    int y = py + i;

    for (int ii =0; ii < 8; ii++)
    {
        x+=1;
        if ((sym & (1 << ii)))
        {
            fb_set_px(x,y,fg);
        }
        else
        {
            fb_set_px(x,y,bg);
        }

    }
}

我也想知道是否可以简化此代码:
void fb_set_px(x,y,hex){
    void*ptr = ((_base + (_bpr*y) + (_bpe*x)));
    unsigned int *p = (unsigned int *) ptr;
    *p=hex;
}

这是行之有效的,因为这里的行太多了,我需要重画整个控制台(滚动),这时会有很大的延迟。

最佳答案

通常,大多数硬件帧缓冲区(例如VGA帧缓冲区)都具有硬件滚动功能。不仅如此,某些帧缓冲区(不幸的是不是VGA字符控制台)将“环绕”,这意味着当您写入帧缓冲区的最后一个字节(或位),然后再次写入第一个字节时帧缓冲区的字节(或位),这些字节将在硬件中显示为屏幕的下一行。因此,您可以做几件事:

  • 完成后,使用帧缓冲区的硬件滚动功能滚动到下一行。这意味着您将首先清除帧缓冲区的下一行,在该行上写入所需的字符,然后将帧缓冲区起始行指针增加一个。然后,这将“出现”,就像帧缓冲区向下滚动了一行一样。当您到达帧缓冲区内存的末尾时,请继续执行相同的过程,但是您要清除的下一行将是帧缓冲区内存中的第一行。然后,您将继续增加帧缓冲区的起始地址(它仍然指向帧缓冲区的内存末端附近的某个地方),直到它也指向帧缓冲区的内存的最后一行为止。然后,您将回绕到内存中的第一行。
  • 如果您的帧缓冲区仍然是多页的,但是不具有环绕功能(例如VGA字符控制台),则保持指向帧缓冲区开始的指针,以及当您到达最后一个“页”,使用memcpy()将内存中的最后一页复制到内存中帧缓冲区的第一页中。完成该步骤后,请保持相同的页面滚动例程,在其中清除下一行,然后增加帧缓冲区的起始行指针,以产生向上滚动单个行的错觉。页面复制将比到那时为止使用的所有其他硬件页面滚动慢一点,但是memcpy()非常有效,尤其是如果您一次使用更大的内存类型(例如long)而不是a来复制多个字节时, char

  • 接下来,就您的访问函数fb_set_px而言,我会:1)在头文件中将它设为inline,以便避免需要使用堆栈来设置激活框架的实际函数调用的开销,以及2)您可以使用事实上,您的帧缓冲区只是一个内存数组,实际上是将指针数组映射到某种struct类型,该类型表示到您的frame_buffer的每个字符的数据布局(即,某些帧缓冲区具有一个字符字节,而另一个应用于字符的某种类型的属性(如颜色等)的字节)。因此,例如,您可以执行以下操作:
    typedef struct frame_buffer_t
    {
        unsigned char character;
        unsigned char attributes;
        //add or omit any fields that describe your frame-buffer data-layout
    } __attribute__((packed)) frame_buffer_t;
    
    //define as global variable
    //make volatile to avoid any compiler re-ordering
    unsigned volatile frame_buffer_t* framebuffer[MAX_ROWS_IN_FRAMEBUFFER];
    
    int main()
    {
        unsigned volatile frame_buffer_t* temp = global_frame_buffer_start_ptr;
    
        for (int i=0; i < MAX_ROWS_IN_FRAMEBUFFER; i++)
        {
            framebuffer[i] = temp;
            temp += NUM_COLUMNS;
        }
    
        //... more code
    }
    

    现在,您可以简单地将帧缓冲区中的x,y位置定为
    framebuffer[Y_POS][X_POS].character = SOME_VALUE;
    

    关于c - 在控制台(帧缓冲区)中绘制字符的最快方法?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6663541/

    10-09 08:10