我试图用Xlib,XF86Vidmode和OpenGL编写一些简单的图形。我有两个问题:
- Xlib似乎不等同于WM_TIMER,因此我写了一个Sigalrm处理程序,该处理程序发送消息以解开消息循环,但是由于这种用法完全是线索,因此该程序会在一段时间后悬挂。因此,我尝试在XCB中进行重新编码。
- xf86vidmode使用尴尬,我不喜欢结果,所以我切换到randr。
完成上述操作后,事实证明XCB有相同的挂起,因此我无法编码封锁消息循环。取而代之的是,我偶尔对程序进行了调查,并且该程序没有悬挂,但是跳过了令人讨厌的框架。
虽然我可以使用randr切换视频模式,但我想使用XCB版本,而XCB版本不起作用。我在XCB上窃了一个@DatenWolf的示例,但XCB_RANDR_GET_SCREEN_INFO_REPLY以某种方式不起作用。它应该将指针返回到一个结构,然后返回屏幕尺寸数组(MM中的尺寸是错误的),然后是刷新率数据。刷新率数据是垃圾,主要是零。我在做什么错?
/*
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 = %pn",display);
connection = XGetXCBConnection(display);
printf("connection = %pn",connection);
XSetEventQueueOwner(display,XCBOwnsEventQueue);
win = xcb_generate_id(connection);
printf("win = %dn",win);
screen_from_Xlib_Display(display,connection,&screen_num,&screen);
printf("screen_num = %dn",screen_num);
printf("screen->root = %dn",screen->root);
FBConfigs = glXChooseFBConfig(display,screen_num,attrib_list,
&nelements);
printf("FBConfig = %pn",FBConfigs);
printf("nelements = %dn",nelements);
fb_config = FBConfigs[0];
visual = glXGetVisualFromFBConfig(display,fb_config);
printf("visual = %pn",visual);
visualID = visual->visualid;
printf("visualID = %dn",visualID);
context = glXCreateNewContext(display,fb_config,GLX_RGBA_TYPE,
0,True);
printf("context = %pn",context);
colormap = xcb_generate_id(connection);
printf("colormap = %dn",colormap);
create_color = xcb_create_colormap_checked(connection,
XCB_COLORMAP_ALLOC_NONE,colormap,screen->root,visualID);
printf("create_color.sequence = %dn",create_color.sequence);
error = xcb_request_check(connection,create_color);
printf("error = %pn",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 = %dn",create_win.sequence);
error = xcb_request_check(connection,create_win);
printf("error = %pn",error);
screen_info = xcb_randr_get_screen_info_unchecked(connection, screen->root);
printf("screen_info.sequence = %dn",screen_info.sequence);
reply = xcb_randr_get_screen_info_reply(connection,screen_info,
NULL);
printf("reply = %pn",reply);
printf("reply->response_type = %dn",reply->response_type);
printf("reply->rotations = %dn",reply->rotations);
printf("reply->sequence = %dn",reply->sequence);
printf("reply->length = %dn",reply->length);
printf("reply->nSizes = %dn",reply->nSizes);
printf("reply->sizeID = %dn",reply->sizeID);
printf("reply->rotation = %dn",reply->rotation);
printf("reply->rate = %dn",reply->rate);
printf("reply->nInfo = %dn",reply->nInfo);
printf("reply+1 = %pn",reply+1);
sizes = xcb_randr_get_screen_info_sizes(reply);
printf("sizes = %pn",sizes);
sizes_length = xcb_randr_get_screen_info_sizes_length(reply);
printf("sizes_length = %dn",sizes_length);
rates_iter = xcb_randr_get_screen_info_rates_iterator(reply);
printf("rates_iter.data = %pn",rates_iter.data);
printf("rates_iter.rem = %dn",rates_iter.rem);
printf("rates_iter.index = %dn",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 = %pn",rates);
rates_length =
xcb_randr_refresh_rates_rates_length(rates_iter.data);
printf("rates_length = %dn",rates_length);
printf("rates[0] = %dn",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 %dn",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_cet_screen_info_inchecked之前,您必须先首先调用xcb_randr_query_query_version with a major_version和MIDAR_VERSION和MISTIM XCB的某些情况和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会减少一个,而不是通过数据 -> nrates减少,因此通过调用此功能将REM无效。这只是XCB第一个规范中的一个错误,现在被冻结了,还是有一些原因?因此,即使第一个问题解决了,取决于REM的计数,零至零也无法正常工作。
我什至发现了为什么randr在屏幕上获得了错误的物理尺寸:物理尺寸可在CM中以EDID字节21:22提供,并且对我的电视是正确的。但是,它们也在描述符1中的MM中给出,而EDID字节66:68和字节84:86中也给出了它们,这些数字对应于电视中的84!当然,三星应该通过向我发送匹配其EDID数据的电视来解决此问题:)
还有另一个问题,因为Edid说,首选视频模式为3840x2150 @ 60 Hz,即使计算机和电视都只有HDMI 1.4,因此指定的像素时钟速率不可能很快。我想这就是为什么Windows 8.1很难启动这台电视的原因,以及为什么Linux和OSX都跳过本机模式并引导到4096x2160 @ 24 Hz,因此当Unity Shell不活跃时,128像素被切碎。。Windows 10的电视没有问题。
我希望回答自己的问题是正确的做法。我以前从未在这个论坛上尝试过。