gpt4 book ai didi

opengl - 使用 xcb 和 randr 获取屏幕信息

转载 作者:行者123 更新时间:2023-12-05 04:11:27 28 4
gpt4 key购买 nike

我尝试使用 Xlib、XF86VidMode 和 OpenGL 编写一些简单的图形。我有两个问题:

  1. Xlib 似乎没有 WM_TIMER 的等价物,所以我写了一个 SIGALRM 处理程序来发送消息以解除消息循环的阻塞,但是由于这种用法完全是线程不安全的,程序会在一段时间后挂起。因此,我尝试在 xcb 中重新编码。
  2. XF86VidMode 使用起来很尴尬,我不喜欢结果,所以我改用 RandR。

完成上述操作后,发现 xcb 也有同样的挂起,所以我无法编写阻塞消息循环。相反,我每隔一段时间就进行一次轮询,程序没有挂起,但有令人讨厌的跳帧。

虽然我可以使用 RandR 切换视频模式,但我想使用 xcb 版本,但它不起作用。我为 xcb 剽窃了@datenwolf 的一个例子,但不知何故 xcb_randr_get_screen_info_reply 不起作用。它应该返回一个指向结构的指针,该结构后跟一个屏幕尺寸数组(以毫米为单位的尺寸是错误的),然后是刷新率数据。刷新率数据是垃圾,大部分为零。我做错了什么?

/*
gcc rrxcb.c -lxcb-randr -lxcb -lX11 -lX11-xcb -lGL -orrxcb
*/

#include <xcb/randr.h>
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xlib-xcb.h>
#include <xcb/xcb.h>
#include <GL/glx.h>
#include <unistd.h>

void screen_from_Xlib_Display(
Display * const display,
xcb_connection_t *connection,
int * const out_screen_num,
xcb_screen_t ** const out_screen)
{
xcb_screen_iterator_t screen_iter = xcb_setup_roots_iterator(xcb_get_setup(connection));
int screen_num = DefaultScreen(display);
while( screen_iter.rem && screen_num > 0 ) {
xcb_screen_next(&screen_iter);
--screen_num;
}
*out_screen_num = screen_num;
*out_screen = screen_iter.data;
}

int main()
{
Display *display;
xcb_connection_t *connection;
xcb_window_t win;
const int GLX_TRUE = True;
int attrib_list[] = {GLX_X_RENDERABLE,GLX_TRUE,
GLX_DRAWABLE_TYPE,GLX_WINDOW_BIT,
GLX_RENDER_TYPE,GLX_RGBA_BIT,
GLX_CONFIG_CAVEAT,GLX_NONE,
GLX_DOUBLEBUFFER,GLX_TRUE,
GLX_BUFFER_SIZE,32,
GLX_DEPTH_SIZE,24,
GLX_STENCIL_SIZE,8,
0};
GLXFBConfig *FBConfigs;
int nelements;
GLXFBConfig fb_config;
XVisualInfo *visual;
int visualID;
GLXContext context;
xcb_colormap_t colormap;
xcb_void_cookie_t create_color;
xcb_void_cookie_t create_win;
const uint32_t eventmask = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS;
const uint32_t valuemask = XCB_CW_EVENT_MASK | XCB_CW_COLORMAP;
uint32_t valuelist[] = {eventmask,colormap};
xcb_randr_get_screen_info_cookie_t screen_info;
xcb_randr_get_screen_info_reply_t *reply;
int screen_num;
xcb_screen_t *screen;
xcb_generic_error_t *error;
xcb_randr_screen_size_t *sizes;
int sizes_length;
xcb_randr_refresh_rates_iterator_t rates_iter;
uint16_t *rates;
int rates_length;
int i;

/* Open Xlib Display */
display = XOpenDisplay(NULL);
printf("display = %p\n",display);
connection = XGetXCBConnection(display);
printf("connection = %p\n",connection);
XSetEventQueueOwner(display,XCBOwnsEventQueue);
win = xcb_generate_id(connection);
printf("win = %d\n",win);
screen_from_Xlib_Display(display,connection,&screen_num,&screen);
printf("screen_num = %d\n",screen_num);
printf("screen->root = %d\n",screen->root);
FBConfigs = glXChooseFBConfig(display,screen_num,attrib_list,
&nelements);
printf("FBConfig = %p\n",FBConfigs);
printf("nelements = %d\n",nelements);
fb_config = FBConfigs[0];
visual = glXGetVisualFromFBConfig(display,fb_config);
printf("visual = %p\n",visual);
visualID = visual->visualid;
printf("visualID = %d\n",visualID);
context = glXCreateNewContext(display,fb_config,GLX_RGBA_TYPE,
0,True);
printf("context = %p\n",context);
colormap = xcb_generate_id(connection);
printf("colormap = %d\n",colormap);
create_color = xcb_create_colormap_checked(connection,
XCB_COLORMAP_ALLOC_NONE,colormap,screen->root,visualID);
printf("create_color.sequence = %d\n",create_color.sequence);
error = xcb_request_check(connection,create_color);
printf("error = %p\n",error);
create_win = xcb_create_window_checked(connection,
XCB_COPY_FROM_PARENT,win, screen->root,0,0,640,480,2,
XCB_WINDOW_CLASS_INPUT_OUTPUT,visualID,valuemask,valuelist);
printf("create_win.sequence = %d\n",create_win.sequence);
error = xcb_request_check(connection,create_win);
printf("error = %p\n",error);
screen_info = xcb_randr_get_screen_info_unchecked(connection, screen->root);
printf("screen_info.sequence = %d\n",screen_info.sequence);
reply = xcb_randr_get_screen_info_reply(connection,screen_info,
NULL);
printf("reply = %p\n",reply);
printf("reply->response_type = %d\n",reply->response_type);
printf("reply->rotations = %d\n",reply->rotations);
printf("reply->sequence = %d\n",reply->sequence);
printf("reply->length = %d\n",reply->length);
printf("reply->nSizes = %d\n",reply->nSizes);
printf("reply->sizeID = %d\n",reply->sizeID);
printf("reply->rotation = %d\n",reply->rotation);
printf("reply->rate = %d\n",reply->rate);
printf("reply->nInfo = %d\n",reply->nInfo);
printf("reply+1 = %p\n",reply+1);
sizes = xcb_randr_get_screen_info_sizes(reply);
printf("sizes = %p\n",sizes);
sizes_length = xcb_randr_get_screen_info_sizes_length(reply);
printf("sizes_length = %d\n",sizes_length);
rates_iter = xcb_randr_get_screen_info_rates_iterator(reply);
printf("rates_iter.data = %p\n",rates_iter.data);
printf("rates_iter.rem = %d\n",rates_iter.rem);
printf("rates_iter.index = %d\n",rates_iter.index);
for( ; rates_iter.rem; xcb_randr_refresh_rates_next(&rates_iter))
{
rates = xcb_randr_refresh_rates_rates(rates_iter.data);
printf("rates = %p\n",rates);
rates_length =
xcb_randr_refresh_rates_rates_length(rates_iter.data);
printf("rates_length = %d\n",rates_length);
printf("rates[0] = %d\n",rates[0]);
/*
for(i = 0; i < rates_length; i++)
{
printf("%d%c",rates[i],(i==rates_length-1)?'\n':' ');
}
*/
}
for(i = 0; i < sizes_length; i++)
{
printf("%d %d %d %d %d\n",i,sizes[i].width,sizes[i].height,sizes[i].mwidth,sizes[i].mheight);
}
return 0;
}

所以我的输出是

display = 0x563687942010
connection = 0x563687943410
win = 54525954
screen_num = 0
screen->root = 241
FBConfig = 0x563687951b20
nelements = 8
visual = 0x563687951d30
visualID = 33
context = 0x563687951680
colormap = 54525956
create_color.sequence = 26
error = (nil)
create_win.sequence = 28
error = (nil)
screen_info.sequence = 31
reply = 0x563687abde30
reply->response_type = 1
reply->rotations = 63
reply->sequence = 31
reply->length = 36
reply->nSizes = 18
reply->sizeID = 1
reply->rotation = 1
reply->rate = 30
reply->nInfo = 53
reply+1 = 0x563687abde50
sizes = 0x563687abde50
sizes_length = 18
rates_iter.data = 0x563687abdee0
rates_iter.rem = 35
rates_iter.index = 176
rates = 0x563687abdee2
rates_length = 0
rates[0] = 0
rates = 0x563687abdee4
rates_length = 0
rates[0] = 0
rates = 0x563687abdee6
rates_length = 0
...
rates = 0x563687add7a8
rates_length = 0
rates[0] = 0
0 4096 2160 1872 1053
1 3840 2160 1872 1053
2 1920 1080 1872 1053
3 1680 1050 1872 1053
4 1600 900 1872 1053
5 1280 1024 1872 1053
6 1440 900 1872 1053
7 1366 768 1872 1053
8 1280 800 1872 1053
9 1152 864 1872 1053
10 1280 720 1872 1053
11 1024 768 1872 1053
12 832 624 1872 1053
13 800 600 1872 1053
14 720 576 1872 1053
15 720 480 1872 1053
16 640 480 1872 1053
17 720 400 1872 1053

谁能发现我做错了什么?

最佳答案

好的,在离开 Linux 一天之后,然后我用头撞了一天这个特定的砖墙,我已经回答了我的大部分问题。 xcb_randr_get_screen_info_reply 没有完全工作的原因是在你调用 xcb_randr_get_screen_info_unchecked 之前,你必须首先调用 xcb_randr_query_version 并将 major_version 和 minor_version 设置为至少 1 或 xcb 认为你的版本低于 1.1 或其他东西并且你没有得到正确设置刷新率数据结构。

然后当我走到这一步时,我在我安装的 xcb/randr.h 中发现了一些可怕的东西:

/**
* Get the next element of the iterator
* @param i Pointer to a xcb_randr_refresh_rates_iterator_t
*
* Get the next element in the iterator. The member rem is
* decreased by one. The member data points to the next
* element. The member index is increased by sizeof(xcb_randr_refresh_rates_t)
*/
void
xcb_randr_refresh_rates_next (xcb_randr_refresh_rates_iterator_t *i /**< */);

看到了吗?成员 rem 减一,而不是 data->nRates,因此 rem 因调用此函数而失效。这只是 xcb 的第一个规范中存在的一个错误,现在被卡住了,还是有一些原因?因此,即使第一个问题得到解决,依靠 rem 倒数到零也行不通。

我什至发现了为什么 RandR 为我的屏幕获取了错误的物理尺寸:物理尺寸以 EDID 字节 21:22 中的厘米为单位可用,并且对我的电视是正确的。然而,它们也在 EDID 字节 66:68 和字节 84:86 中的描述符 1 和描述符 2 中以毫米为单位给出,这些数字对应于电视中的 84!当然,三星应该通过向我发送与他们的 EDID 数据相匹配的电视来解决这个问题:)

还有一个问题是 EDID 表示首选视频模式是 3840x2150 @ 60 Hz,即使计算机和电视都只有 HDMI 1.4,所以指定的像素时钟速率快得不可思议。我想这就是为什么 Windows 8.1 很难用这台电视启动,以及为什么 Linux 和 OSX 都跳过 native 模式并启动到 4096x2160 @ 24 Hz,所以当 Unity shell 不活动时,两侧的 128 像素被切掉.不过,Windows 10 在电视上没有问题。

我希望回答我自己的问题是正确的做法;我以前从未在这个论坛上尝试过。

关于opengl - 使用 xcb 和 randr 获取屏幕信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42620138/

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