我试图用Xlib、XF86VidMode和OpenGL编写一些简单的图形。我有两个问题:
完成上述操作后,原来xcb具有相同的挂起,所以我无法编写阻塞消息循环。相反,我每隔一段时间就进行一次民意测验,程序没有挂起,但是有一些跳过的帧令人讨厌。
虽然我可以用RandR切换视频模式,但我想使用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 = %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有人能发现我做错了什么吗?
发布于 2017-03-08 06:29:08
好吧,在离开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/r.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减少1,而不是数据->nRates,因此rem因调用此函数而失效。这仅仅是xcb的第一个规范中的一个bug,现在已经被冻结了,还是有什么原因呢?因此,即使第一个问题是固定的,取决于rem计数到零是行不通的。
我甚至发现了为什么RandR为我的屏幕获取了错误的物理维度:物理维度以厘米为单位,以EDID字节21:22为单位,对我的电视来说是正确的。然而,它们也是以mm表示的描述符1和描述符2( EDID字节66:68和字节84:86 ),这些数字对应于TV中的84!当然,三星应该通过发送一台与EDID数据相匹配的电视机来解决这个问题:)
还有一个问题是,EDID表示首选的视频模式是3840x2150 @ 60 Hz,尽管计算机和电视都只有HDMI 1.4,所以指定的像素时钟速率是不可能的。我想这就是为什么Windows 8.1很难用这台电视机启动,以及为什么Linux和OSX都跳过本机模式并引导到4096x2160 @ 24 Hz,所以当Unity没有激活时,将其中的128个像素从任何一方切断。然而,Windows 10对电视机没有任何问题。
我希望回答我自己的问题是正确的;我以前从未在这个论坛上尝试过这一点。
https://stackoverflow.com/questions/42620138
复制相似问题