【问题标题】:wsdisplay color map not being retrieved correctlywsdisplay 颜色映射未正确检索
【发布时间】:2012-04-14 17:29:20
【问题描述】:

我最近一直在尝试在 NetBSD 5.1.2(使用 VESA 帧缓冲实现)上使用 wscons 和 wsdisplay,但遇到了一点问题:

我可以成功设置彩色图并且它们看起来正确,但是获取彩色图似乎返回了不正确的数据,这样当我尝试程序完成后恢复原始颜色图,所有颜色都不正确:

这是导致问题的简化程序(请注意,它必须以root 或用户登录第二个虚拟终端 (/dev/ttyE1) 的身份运行):

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <dev/wscons/wsconsio.h>

int main(int argc, char **argv) {
    (void)argc, (void)argv;
    int tty = open("/dev/ttyE1", O_RDWR | O_EXCL);
    if(tty == -1) {
        perror("error opening tty");
        return EXIT_FAILURE;
    }
    struct wsdisplay_fbinfo fbinfo;
    if(ioctl(tty, WSDISPLAYIO_GINFO, &fbinfo) == -1) {
        perror("error retrieving framebuffer info");
        close(tty);
        return EXIT_FAILURE;
    }
    uint8_t *cmap_data = malloc(fbinfo.cmsize * 3);
    if(cmap_data == NULL) {
        perror("error allocating memory for color map data");
        close(tty);
        return EXIT_FAILURE;
    }
    struct wsdisplay_cmap cmap;
    cmap.index = 0;
    cmap.count = fbinfo.cmsize;
    cmap.red   = &cmap_data[fbinfo.cmsize * 0];
    cmap.green = &cmap_data[fbinfo.cmsize * 1];
    cmap.blue  = &cmap_data[fbinfo.cmsize * 2];
    if(ioctl(tty, WSDISPLAYIO_GETCMAP, &cmap) == -1) {
        perror("error getting color map");
        close(tty), free(cmap_data);
        return EXIT_FAILURE;
    }
    if(ioctl(tty, WSDISPLAYIO_PUTCMAP, &cmap) == -1) {
        perror("error putting color map");
        close(tty), free(cmap_data);
        return EXIT_FAILURE;
    }
    free(cmap_data);
    close(tty);
    return EXIT_SUCCESS;
}

我做错了什么以及如何让它正确检索和恢复颜色图?

【问题讨论】:

    标签: c color-palette netbsd


    【解决方案1】:

    原因

    我进一步研究了这个问题,似乎某些内核内存未初始化或损坏。具体来说,struct vesafb_softc 的 sc_cmap_red、sc_cmap_green 和 sc_cmap_blue(在第 89 到 91 行的 vesafbvar.h 中)包含不正确的数据。这有点令人惊讶,因为vesafb.c 的第 719 到 722 行对其进行了初始化:

    /* Fill in the softc colourmap arrays */
    sc->sc_cmap_red[i / 3] = rasops_cmap[i + 0];
    sc->sc_cmap_green[i / 3] = rasops_cmap[i + 1];
    sc->sc_cmap_blue[i / 3] = rasops_cmap[i + 2];
    

    即使我将其移出它所在的 if 语句,它也包含不正确的数据,因此它可能已损坏而不是未初始化。

    但是,驱动程序能够正确获取和设置颜色图;它似乎无法正确获取struct vesafb_softc 中的第一个。

    解决方法

    一个简单的解决方案是让程序重新设置默认颜色图。正如上面的 sn-p 所指出的,应该从rasops_cmap 获取其初始颜色,这恰好在rasops.c 的第 55 到 122 行定义:

    /* ANSI colormap (R,G,B). Upper 8 are high-intensity */
    const u_char rasops_cmap[256*3] = {
        /* ... */
    };
    

    使用这些颜色,您可以制作一个程序,将其设置为当前颜色图。我必须进行一些更改,以使光标不会消失,但它大部分都有效。

    更好的解决方案

    当我四处寻找更多信息时,我找到了this blog post。当我使用genfb(4) 而不是vesafb(4) 重新编译内核时,内核在启动时挂起。原来这是因为我使用的引导加载程序不够新,无法将所需的参数传递给内核。

    我碰巧看了NetBSD 6.0 changelog 并注意到了这个条目:

    • amd64, i386
      引导加载程序已得到增强,以支持使用 VESA BIOS 扩展的帧缓冲控制台。这些更改允许 x86 端口与 genfb(4) 驱动程序一起使用,并废弃了仅 i386 的 vesafb(4) 驱动程序。 [jmcneill 20090216]

    我下载了 NetBSD 6.0_BETA 并从启动提示符启动它,如下所示:

    > vesa 640x480x8
    > boot netbsd
    

    ...一切正常。

    简而言之,使用较新版本的 NetBSD 并放弃 vesafb(4) 即可解决问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-17
      • 2020-08-02
      • 1970-01-01
      • 2023-01-12
      • 2016-10-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多