打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
linux – 如果“纯XCB”OpenGL是不可能的,那么在xcb / glx.h中找到的XCB / GLX API的用途是什么?

官方的XCB文档告诉我们using OpenGL purely with XCB is impossible:一个人也必须使用Xlib.

巴特梅西(XCB的创始人)This post并未暗示这应该是不可能的.但我确定我错过了一些东西.

我花了好几个小时浏览xcb / glx.h,它组织得很好here.在我看来,它就像一个完整的API.但我无法让它发挥作用.

问题

> XCB / GLX API无用吗? xcb / glx.h的目的是什么?
>如何使用API​​?

(注意:这是了解XCB如何工作的持续努力的一部分.)

相关SO thread.

次要的,啰嗦的东西

如果有人愿意采取行动,这里是来自XCB邮件列表中原始帖子的来源,删除了一点并放入一个文件中.

您会注意到xcb_glx_make_context_current返回错误169(不知道这意味着什么),但前提是xcb_glx_create_window为其最后两个参数取0和NULL.这些参数涉及一系列属性,它们似乎是由函数xcb_glx_create_window_attribs返回的,但我无法弄清楚如何使用它…

int main()之前的长辅助函数仅表示两个返回两个整数xcb_glx_fbconfig_t fbconfig xcb_visualid_t glx_visual,对应于第一个“匹配”帧缓冲配置.在我的平台上,这些是0xa7和0x24.它们正是Xlib / GLX例程(实际工作)返回的原因,所以我知道我选择的帧缓冲配置很好.

所以,问题似乎发生在xcb_glx_create_window和xcb_glx_make_context_current之间…

// gcc main2.c -o main -lxcb -lxcb-glx -lGL && ./main2// TODO free replies#include <stdio.h>#include <stdlib.h>#include <xcb/glx.h>#include <GL/gl.h>#define W 1024#define H 1024// parameter types returned by xcb_glx_get_fb_configs#define GLX_DRAWABLE_TYPE               0x8010#define GLX_RENDER_TYPE                 0x8011#define GLX_DOUBLEBUFFER                5#define GLX_RED_SIZE                    8#define GLX_GREEN_SIZE                  9#define GLX_BLUE_SIZE                   10#define GLX_RGBA_BIT                    0x00000001#define GLX_RGBA_TYPE                   0x8014#define GLX_STENCIL_SIZE                13#define GLX_DEPTH_SIZE                  12#define GLX_BUFFER_SIZE                 2#define GLX_ALPHA_SIZE                  11#define GLX_X_RENDERABLE                0x8012#define GLX_FBCONFIG_ID                 0x8013#define GLX_VISUAL_ID                   0x800b#define GLX_WINDOW_BIT                  0x00000001#define GLX_PIXMAP_BIT                  0x00000002#define GLX_PBUFFER_BIT                 0x00000004// ------------------------------------------------------------------------------------------------// fbconfig and visual?uint32_t glx_attrs[] = {  GLX_DOUBLEBUFFER, 1,  GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT|GLX_PIXMAP_BIT|GLX_PBUFFER_BIT,  GLX_X_RENDERABLE, 1,    GLX_RED_SIZE, 8,  GLX_GREEN_SIZE, 8,  GLX_BLUE_SIZE, 8,  GLX_ALPHA_SIZE, 8,  GLX_STENCIL_SIZE, 8,  GLX_DEPTH_SIZE, 24,  GLX_BUFFER_SIZE, 32,  GLX_RENDER_TYPE, GLX_RGBA_BIT,};// ------------------------------------------------------------------------------------------------// This function searches for an @param prop_name in the @param property list of properties of size @param prop. Prop is property count and not buffer size.uint32_t glx_get_property(const uint32_t* property, const uint props, uint32_t prop_name){  uint i=0;  while(i < props*2){      if(property[i] == prop_name)        return property[i 1];      else i  = 2;  }  return -1;}// This function chooses and returns specific fbconfig id depending on attributes specified in // @param attrib list. @param attribsz is the number of properties(not list size)int32_t glx_choose_fbconfig(xcb_connection_t* connection, uint32_t screen_num, uint32_t* attrib, uint32_t attribsz){  xcb_generic_error_t* xerror;  xcb_glx_get_fb_configs_reply_t* fbconfigs = xcb_glx_get_fb_configs_reply(connection, xcb_glx_get_fb_configs(connection, screen_num), NULL);  uint32_t* prop = xcb_glx_get_fb_configs_property_list(fbconfigs);  uint32_t* fbconfig_line   = prop;  uint32_t  fbconfig_linesz = fbconfigs->num_properties * 2;  for(uint i=0 ; i<fbconfigs->num_FB_configs; i  ){  // for each fbconfig line      uint good_fbconfig = 1;    for(uint j=0 ; j<attribsz*2; j  = 2){  // for each attrib    // if property found != property given        if(glx_get_property(fbconfig_line, fbconfigs->num_properties, attrib[j]) != attrib[j 1]) {            good_fbconfig = 0; // invalidate this fbconfig entry, sine one of the attribs doesn't match            break;        }    }    // if all attribs matched, return with fid    if(good_fbconfig){        uint32_t fbconfig_id = glx_get_property(fbconfig_line, fbconfigs->num_properties , GLX_FBCONFIG_ID);        free(fbconfigs);        return fbconfig_id;    }    fbconfig_line  = fbconfig_linesz; // next fbconfig line;  }  return -1;}// This function returns @param attrib value from a line containing GLX_FBCONFIG_ID of @param fid// It kind of queries particular fbconfig line for a specific property.uint32_t glx_get_attrib_from_fbconfig(xcb_connection_t* connection, uint32_t screen_num, uint32_t fid, uint32_t attrib){  xcb_glx_get_fb_configs_reply_t* fbconfigs = xcb_glx_get_fb_configs_reply(connection, xcb_glx_get_fb_configs(connection, screen_num), NULL);  uint32_t* prop   = xcb_glx_get_fb_configs_property_list(fbconfigs);  uint i = 0;  uint fid_found = 0;  while(i < fbconfigs->length){    if(prop[i] == GLX_FBCONFIG_ID) {      if(prop[i 1] == fid){        fid_found = 1;        i -= i%(fbconfigs->num_properties * 2); // going to start of the fbconfig  line        uint32_t attrib_value = glx_get_property(&prop[i], fbconfigs->num_properties, attrib);        free(fbconfigs);        return attrib_value;      }    }    i =2;  }  if(fid_found) printf("glx_get_attrib_from_fbconfig: no attrib %u was found in a fbconfig with GLX_FBCONFIG_ID %u\n", attrib, fid);  else printf("glx_get_attrib_from_fbconfig: GLX_FBCONFIG_ID %u was not found!\n", fid);  return -1;}// ------------------------------------------------------------------------------------------------int main(){  xcb_generic_error_t* xerror; // To hold errors!  int screen_number;  xcb_connection_t* connection = xcb_connect(NULL, &screen_number);  xcb_screen_t* screen = xcb_setup_roots_iterator(xcb_get_setup(connection)).data;   // getting the default screen  printf("screen %d  root %d\n", screen_number, screen->root);  xcb_colormap_t    colormap    = xcb_generate_id(connection);  // generating XID's for our objects!  xcb_window_t      window      = xcb_generate_id(connection);  xcb_glx_context_t glx_context = xcb_generate_id(connection);  xcb_glx_window_t  glx_window  = xcb_generate_id(connection);  // ----------------------------------------------------------------------------------------------  xcb_glx_query_version_reply_t* glx_version = xcb_glx_query_version_reply(connection, xcb_glx_query_version(connection, 0, 0), NULL);  printf("glx %d.%d  response_type %x  pad0 %x  sequence %x  length %d\n",    glx_version->major_version, glx_version->minor_version, glx_version->response_type,    glx_version->pad0, glx_version->sequence, glx_version->length);  // ----------------------------------------------------------------------------------------------  xcb_glx_fbconfig_t fbconfig   = glx_choose_fbconfig(connection, screen_number, glx_attrs, sizeof(glx_attrs)/2/sizeof(uint32_t));  xcb_visualid_t glx_visual     = glx_get_attrib_from_fbconfig(connection, screen_number, fbconfig, GLX_VISUAL_ID);  printf("fbconfig %x  glx_visual %x\n", fbconfig, glx_visual);  // ----------------------------------------------------------------------------------------------  xcb_glx_create_new_context(connection, glx_context, fbconfig, screen_number, GLX_RGBA_TYPE, 0, 1);  // New-style context?  // xcb_glx_create_context(connection, glx_context, glx_visual, 0, 0, 1);  // Alt method! Old-style context?  if(!(xcb_glx_is_direct_reply(connection, xcb_glx_is_direct(connection, glx_context), NULL)->is_direct))    puts("glx context is not direct!");  // ----------------------------------------------------------------------------------------------  xcb_create_colormap(connection , XCB_COLORMAP_ALLOC_NONE, colormap, screen->root, glx_visual);  // creating colormap  // creating a window, using our new colormap  uint32_t window_mask = XCB_CW_BACK_PIXEL|XCB_CW_EVENT_MASK|XCB_CW_COLORMAP;  uint32_t window_attrs[] = {0x444444, XCB_EVENT_MASK_EXPOSURE|XCB_EVENT_MASK_KEY_PRESS, colormap};  xcb_create_window(connection, screen->root_depth, window, screen->root, 0,0, W,H, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, glx_visual, window_mask, window_attrs);  xcb_map_window(connection, window);  xcb_glx_create_window(connection, screen_number, fbconfig, window, glx_window, 0, NULL);  xcb_flush(connection);  // ----------------------------------------------------------------------------------------------  xcb_glx_make_context_current_reply_t* reply_ctx = xcb_glx_make_context_current_reply(connection, xcb_glx_make_context_current(connection, 0, glx_window, glx_window, glx_context), NULL);  if(!reply_ctx)  puts("ERROR  xcb_glx_make_context_current returned NULL!");  xcb_glx_context_tag_t glx_context_tag = reply_ctx->context_tag;  // alternative ?  // xcb_glx_make_current_reply_t* reply_mc = xcb_glx_make_current_reply(connection, xcb_glx_make_current(connection, glx_window, glx_context, 0), NULL);  // xcb_glx_context_tag_t glx_context_tag = reply_mc->context_tag;  // ----------------------------------------------------------------------------------------------  xcb_glx_get_error_reply(connection, xcb_glx_get_error(connection, glx_context_tag), &xerror);  if(xerror)  printf("\nERROR  xcb_glx_get_error %d\n", xerror->error_code);  // ----------------------------------------------------------------------------------------------  xcb_generic_event_t* event;  uint running = 1;  while(running){    event = xcb_poll_for_event(connection);    if(event){      switch (event->response_type) {        case XCB_EXPOSE:          glClearColor(0, .5, 1, 1);  // Blue          glFlush();          xcb_glx_swap_buffers(connection, glx_context_tag, glx_window);          puts("Expose!");          break;        case XCB_KEY_PRESS: // exit on key press          running = 0;          break;      }    }    free(event);  }  xcb_disconnect(connection);}

解决方法:

这里需要了解的重要事项是XCB函数直接映射到X11协议请求.这意味着xcb_glx_ *函数直接映射到X11 GLX协议请求.请参阅https://www.khronos.org/registry/OpenGL/specs/gl/glx1.4.pdf中的“第4章”.它列出了所有可用的GLX请求.例如,glAreTexturesResident从xcb / glx.h(https://xcb.freedesktop.org/manual/glx_8h_source.html)映射到xcb_glx_are_textures_resident_ * API.在Khronos规范中,您可以阅读请求做什么.

What’s the purpose of xcb/glx.h?

XCB-GLX只与X服务器通信,它不执行任何硬件初始化或触摸OpenGL客户端状态.因此,XCB-GLX不能用作GLX API的替代品. [1]

硬件初始化和其他GL内容由openGL lib完成.这就是规范的“另一半”实施的地方.在Linux上,libsa由mesa(https://cgit.freedesktop.org/mesa/mesa/tree/src/glx)提供.你可以看到glx目录中的文件包含Xlib.h,所以我想这就是Xlib依赖的来源.这解释了“GLX API与Xlib紧密结合.因此,X Windows上的OpenGL应用程序必须使用Xlib,因此不能仅使用XCB.” [1].

Is the XCB/GLX API useless?

虽然XCB-GLX API对最终用户XCB应用程序开发人员没什么价值,但它可以用于开发基于XCB的新OpenGL和GLX实现. XCB可以提高OpenGL库的速度和质量. [1]

因此,为了获得纯XCB GLX,有人需要在openGL lib中重新实现GLX:

>公开基于XCB的API以初始化硬件等.
>应该使用xcb_glx API与X服务器进行通信,而不是Xlib.

来自[1]的文档说“GLX系统有两个角色,它与X服务器通信并初始化客户端和硬件状态.”

xcb-glx负责沟通.另一个角色(基于XCB的OpenGL和GLX实现)目前尚未实现,也不太可能实现.

“GLX API是根据Xlib指定的,glX函数使用Xlib Displays,Windows,Visuals等.GLX实现也是使用Xlib构建的.” (参见libGL.so的导出符号).为了完成第二个角色,我们需要一个使用XCB连接,窗口,视觉效果的相同API.

[1] https://xcb.freedesktop.org/opengl/

免责声明:这是我对收集的理解.

来源:https://www.icode9.com/content-3-274751.html
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
61板实现位操作的头文件
跨平台C++ MD5类库
Java与C++实现相同的MD5加密算法
Android Sensors Development(HAL有参考价值)
Wayland download and compile | 学步园
Qt编译时所需要的全部库文件大全
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服