gpt4 book ai didi

c - wsdisplay 颜色图未正确检索

转载 作者:行者123 更新时间:2023-11-30 19:49:53 24 4
gpt4 key购买 nike

我一直在尝试使用wsconswsdisplay最近在 NetBSD 5.1.2(使用 VESA 帧缓冲区实现)上遇到了一些问题:

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

Vim, showing the program's source with a strange color map

这是一个导致问题的简化程序(请注意,它必须以 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;
}

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

最佳答案

原因

我进一步研究了这个问题,发现某些内核内存要么未初始化,要么已损坏。具体来说,struct vesafb_softcsc_cmap_redsc_cmap_greensc_cmap_blue(在 vesafbvar.h 第 89 到 91 行)包含不正确的数据。这有点令人惊讶,因为 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 中的第一个。

解决方法

一个简单的解决方案是让程序重新设置默认颜色图。正如上面的代码片段所示,它应该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
    The bootloader has been enhanced to support framebuffer consoles using VESA BIOS extensions. These changes allow the x86 ports to work with the genfb(4) driver, and obsoletes the i386-only vesafb(4) driver. [jmcneill 20090216]

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

> vesa 640x480x8
> boot netbsd

...一切正常。

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

关于c - wsdisplay 颜色图未正确检索,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9952971/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com