一页水滴 2023-07-09 18:20 采纳率: 0%
浏览 13

X11 XCB SHM linux 图像渲染, 折腾不成功,帮我看看代码哪里有问题,如何解决?(语言-c语言)

在linux 下用 xcb 基于 共享内存shm 做简单的图像渲染,对接口不太熟悉,折腾不成功。帮我看看哪里出问题,我的代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <xcb/xcb.h>

#include <xcb/shm.h>
#include <sys/shm.h>
#include <sys/mman.h>
#include <xcb/xproto.h>
#include <unistd.h>
#include <errno.h>
// 定义图像宽度和高度
#define IMAGE_WIDTH 640
#define IMAGE_HEIGHT 480
#define IMAGE_SIZE (IMAGE_WIDTH * IMAGE_HEIGHT * 3)  //921,600


int main() {
    xcb_void_cookie_t cookie;
    xcb_generic_error_t *pError;
    char *framebuffer;
    // 连接到 X 服务器
    xcb_connection_t *connection = xcb_connect(NULL, NULL);
    if (xcb_connection_has_error(connection)) {
        printf("Error: Failed to connect to X server(%s)\n", strerror(errno));
        return 1;
    }

    // 获取默认屏幕
    xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(connection)).data;

    // 创建 XCB 窗口
    xcb_window_t windowId = xcb_generate_id(connection);
    cookie = xcb_create_window_checked(connection, XCB_COPY_FROM_PARENT, windowId, screen->root,
                      0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 0, XCB_WINDOW_CLASS_COPY_FROM_PARENT,
                      screen->root_visual, 0, NULL);
    pError = xcb_request_check(connection, cookie);
    if (pError){
        printf("xcb_create_window fail(%s)\n", strerror(errno));
        free(pError);
        goto out;
    }

    // 获取 XCB 窗口的可视图像
    // xcb_visualid_t visual = screen->root_visual;
    xcb_gcontext_t gc = xcb_generate_id(connection);
    cookie = xcb_create_gc_checked(connection, gc, screen->root, 0, NULL);
    pError = xcb_request_check(connection, cookie);
    if (pError){
        printf("xcb_create_gc fail(%s)\n", strerror(errno));
        free(pError);
        goto out;
    }

    // 创建共享内存段
    xcb_shm_seg_t shmseg = xcb_generate_id(connection);
    xcb_shm_create_segment_cookie_t createSegmentCookie = xcb_shm_create_segment(connection, shmseg, IMAGE_WIDTH * IMAGE_HEIGHT * 3, 0);
    xcb_shm_create_segment_reply_t *reply = xcb_shm_create_segment_reply(connection, createSegmentCookie, &pError);
    if (!reply){
        printf("xcb_shm_create_segment fail(%s)\n", strerror(errno));
        goto out;
    }
    if (pError){
        printf("xcb_shm_create_segment_reply fail(%s)\n", strerror(errno));
        goto out;
    }
    int *fds = xcb_shm_create_segment_reply_fds(connection, reply);
    if (reply->nfd != 1) {
        for (int i = 0; i < reply->nfd; i++){
            close(fds[i]);
        }
        printf("xcb_shm_create_segment_reply_fds fail(%s)\n", strerror(errno));
        goto out;
    }
    printf("nfd = %d, fds[0] = %d\n", reply->nfd, fds[0]);

    framebuffer = mmap(NULL, IMAGE_SIZE,  PROT_READ|PROT_WRITE, MAP_SHARED, fds[0], 0);
    if (framebuffer == NULL){
        printf("mmap fail(%s)\n", strerror(errno));
        goto out;
    }
    
    
    cookie = xcb_shm_attach_fd_checked(connection, shmseg, fds[0], 0);
    pError = xcb_request_check(connection, cookie);
    if (pError){
        printf("xcb_shm_attach_fd_checked fail(%s)\n", strerror(errno));
        goto out;
    }

    // 设置 XCB 窗口的属性
    uint32_t values[3];
    values[0] = XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_BUTTON_RELEASE;
    xcb_change_window_attributes(connection, windowId, XCB_CW_EVENT_MASK, values);

    // 显示 XCB 窗口
    xcb_map_window(connection, windowId);
    xcb_flush(connection);

    // 绘制图像
    while (1) {
        // 等待窗口曝光事件
        xcb_generic_event_t *event;
        event = xcb_wait_for_event(connection);
        switch (event->response_type) {
            case XCB_KEY_RELEASE: {
                xcb_key_release_event_t * key = (xcb_key_release_event_t *)event;
                if (key->detail == 10) {
                    printf("XCB_KEY_RELEASE  key detail = %d\n", key->detail);
                    memset(framebuffer, 0, IMAGE_SIZE);
                    cookie = xcb_shm_put_image_checked(connection, windowId, gc, IMAGE_WIDTH, IMAGE_HEIGHT, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, 0, 0, 24, XCB_IMAGE_FORMAT_Z_PIXMAP, 0, shmseg, 0);
                    pError = xcb_request_check(connection, cookie);
                    if (pError){
                        printf("xcb_shm_put_image fail(%s)\n", strerror(errno));
                    }
                    xcb_flush (connection);
                } else if (key->detail == 11) {
                    printf("XCB_KEY_RELEASE  key detail = %d\n", key->detail);
                    memset(framebuffer, 0xff, IMAGE_SIZE);
                    cookie = xcb_shm_put_image_checked(connection, windowId, gc, IMAGE_WIDTH, IMAGE_HEIGHT, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT,
                                    0, 0, 24, XCB_IMAGE_FORMAT_Z_PIXMAP, 0, shmseg, 0);
                    pError = xcb_request_check(connection, cookie);
                    if (pError){
                        printf("xcb_shm_put_image fail(%s)\n", strerror(errno));
                    }
                    xcb_flush (connection);
                } else if (key->detail == 9) {
                    printf("out\n");
                    goto out;
                }
                break;
            }
            default:
                break;
        }
            
            
        free(event);
    }
out:
    // 分离共享内存和销毁共享内存段
    xcb_shm_detach(connection, shmseg);
    
    // 关闭连接并清理资源
    xcb_disconnect(connection);
    return 0;
}



  • 写回答

1条回答 默认 最新

  • 黑客CN 2023-07-11 16:13
    关注

    首先,需要了解一下你的具体问题,你的代码在哪里出现了问题,以及你的错误信息是什么。
    如果你遇到了X11 XCB SHM图像渲染方面的问题,我可以提供一些常见的问题和解决方案。

    1. 问题:无法链接到X11库
      解决方案:在编译时,需要确保已将-X11添加到链接器命令中,例如:
      gcc -o yourprogram yourprogram.c -lX11
      
    2. 问题:无法链接到XCB库
      解决方案:在编译时,需要确保已将-lxcb添加到链接器命令中,例如:
      gcc -o yourprogram yourprogram.c -lxcb
      
    3. 问题:无法链接到XSHM库
      解决方案:在编译时,需要确保已将-lXext添加到链接器命令中,例如:
      gcc -o yourprogram yourprogram.c -lXext
      
    4. 问题:无法创建XCB连接
      解决方案:确保正确地设置DISPLAY环境变量。如果你的程序不是在X窗口系统上运行的,那么可能需要使用Xvfb或其他虚拟X服务器来创建X连接。
    5. 问题:无法获取XCB窗口
      解决方案:确保你已经成功创建了XCB连接,并使用xcb_create_window函数创建了一个窗口,例如:
      ```
      xcb_connection_t *connection = xcb_connect(NULL, NULL);
      xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(connection)).data;
      xcb_window_t window = xcb_generate_id(connection);

    xcb_create_window(connection, XCB_COPY_FROM_PARENT, window, screen->root, 0, 0, 640, 480, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, 0, NULL);

    ```
    以上是一些常见的问题和解决方案,如果你的问题无法通过上述方法解决,建议提供具体的代码和错误信息,以便更好地帮助你解决问题。

    评论

报告相同问题?

问题事件

  • 创建了问题 7月9日

悬赏问题

  • ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
  • ¥15 java写代码遇到问题,求帮助
  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?
  • ¥15 加热介质是液体,换热器壳侧导热系数和总的导热系数怎么算
  • ¥100 嵌入式系统基于PIC16F882和热敏电阻的数字温度计