2017-03-06 8 views
0

Xlib、XF86VidMode、およびOpenGLで簡単なグラフィックを作成しようとしていました。私は2つの問題があった:xcbとrandrで画面情報を取得する

    XlibはWM_TIMERと同等のものを持っていないようですので、私はメッセージループのブロックを解除するために、メッセージを送ったSIGALRMハンドラを書いたが、そのような使い方は完全にスレッド安全ではないことから、プログラム
  1. 少し後にハングアップします。したがって、私は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 

誰もが私が間違っているの何見つけることができますか?

答えて

0

OK、Linuxから休みを取り、その後、この特定のレンガの壁に対して私の頭を叩いて、私は私の質問のほとんどに答えました。 xcb_randr_get_screen_info_replyが完全に機能しなかった理由は、xcb_randr_get_screen_info_uncheckedを呼び出す前に、major_versionとminor_versionの両方が少なくとも1に設定されているxcb_randr_query_versionを最初に呼び出さなければならないか、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ではなく、1減らされます。したがって、remはこの関数の呼び出しによって無効になります。これはxcbの最初の仕様にあったバグで、今は固定されているのですか、それとも何らかの理由がありますか?したがって、最初の問題が修正されても、remに応じてゼロにカウントダウンすることはできませんでした。

RandRが私の画面に間違った物理ディメンションを取得する理由を発見しました。物理ディメンションはEDIDバイト21:22でcm単位で表示され、自分のTVに適しています。しかし、EDIDバイト66:68とバイト84:86のディスクリプタ1とディスクリプタ2のmm単位でも指定されており、これらの数値はTVの84に対応しています!もちろん、SamsungはEDIDデータと一致するTVを私に送ることでこの問題を解決する必要があります:)

EDIDは、コンピュータとテレビの両方でも、ビデオモードが3840x2150 @ 60Hzであると言っているという別の問題がありますHDMI 1.4を使用しているため、指定されたピクセルクロックレートは非常に高速です。私はWindows 8.1がこのTVで起動するのは難しいのですが、LinuxとOSXの両方がネイティブモードをスキップして4096x2160 @ 24 Hzにブートする理由は、Unityシェルがアクティブでないときに128ピクセルが片側。しかし、Windows 10ではテレビに問題はありません。

私自身の質問に答えることが正しいことを願っています。私はこのフォーラムでこれまでに試みたことはありません。

関連する問題