这是indexloc提供的服务,不要输入任何密码
Skip to content

[Bug]: dri3: xcb_dri3_buffers_from_pixmap not working #841

@kde-yyds

Description

@kde-yyds

Background

I have two devices, one is Redmi Note 11T Pro+ (mtk device) (currently using it because of LCD), the other Redmi K60 (qcom device) (already sold out).
For years I always dream of running a full accelerated KDE Plasma in a container in termux-x11.
On Redmi K60, turnip works well on termux x11 with dri3 and performance is good. Zink also works. Then I want to run kwin_x11, but it only renders window frame including title bar and shadow. The window content is full transparent.
On Redmi Note 11T Pro+ sadly there is no such native high performance open source vulkan driver like turnip. So I used sysvk with vulkan-wsi-layer (from @xMeM) on libhybris in gnu/linux container. Vulkan now also works well with dri3 on termux-x11. Zink also works. The performance is also good. (See more in https://github.com/kde-yyds/android-vulkan-bridge)
Image
Then I tried to run kwin_x11 but it has the same effect on turnip zink (and freedreno).
Image
Image
The key problem is likely to be the bad pixmap error. MESA: error: kopper: could not create texture from pixmap (4).

About the dri3 issue

Then I searched for the error message and found:
mesa-24.2.7/src/gallium/frontends/dri/kopper.c:

#ifdef HAVE_DRI3_MODIFIERS
   if (drawable->has_modifiers) {
      xcb_dri3_buffers_from_pixmap_cookie_t bps_cookie;
      xcb_dri3_buffers_from_pixmap_reply_t *bps_reply;
      xcb_generic_error_t *error;

      bps_cookie = xcb_dri3_buffers_from_pixmap(conn, pixmap);
      bps_reply = xcb_dri3_buffers_from_pixmap_reply(conn, bps_cookie, &error);
      if (!bps_reply) {
         mesa_loge("kopper: could not create texture from pixmap (%u)", error->error_code);
         return NULL;
      }
      drawable->image =
         dri3_create_image_from_buffers(conn, bps_reply, fourcc,
                                        screen, &driVkImageExtension,
                                        drawable);
      if (!drawable->image)
         return NULL;
      width = bps_reply->width;
      height = bps_reply->height;
      free(bps_reply);
   } else
#endif

It returns NULL here to avoid crash. So by commenting the early return here I got a bt.

Thread 1 "kwin_x11" received signal SIGSEGV, Segmentation fault.
kopper_get_pixmap_buffer () at ../mesa-24.2.7/src/gallium/frontends/dri/kopper.c:360
360              dri3_create_image_from_buffers(conn, bps_reply, fourcc,
(gdb) bt
#0  kopper_get_pixmap_buffer () at ../mesa-24.2.7/src/gallium/frontends/dri/kopper.c:360
#1  kopper_allocate_textures () at ../mesa-24.2.7/src/gallium/frontends/dri/kopper.c:557
#2  0x0000007feef48174 in dri_st_framebuffer_validate () at ../mesa-24.2.7/src/gallium/frontends/dri/dri_drawable.c:79
#3  0x0000007feef47e94 in dri_drawable_validate_att () at ../mesa-24.2.7/src/gallium/frontends/dri/dri_drawable.c:249
#4  dri_set_tex_buffer2 () at ../mesa-24.2.7/src/gallium/frontends/dri/dri_drawable.c:266
#5  0x00000055555ca4a8 in ?? ()
#6  0x00000055555ca5d8 in ?? ()
#7  0x0000007ff7655ed4 in KWin::SurfaceItem::preprocess() () from /usr/lib/libkwin.so.6
#8  0x0000007ff764bd9c in KWin::ItemRendererOpenGL::createRenderNode(KWin::Item*, KWin::ItemRendererOpenGL::RenderContext*)
    () from /usr/lib/libkwin.so.6
#9  0x0000007ff764c3c8 in KWin::ItemRendererOpenGL::createRenderNode(KWin::Item*, KWin::ItemRendererOpenGL::RenderContext*)
    () from /usr/lib/libkwin.so.6
#10 0x0000007ff764ce80 in KWin::ItemRendererOpenGL::renderItem(KWin::RenderTarget const&, KWin::RenderViewport const&, KWin::Item*, int, QRegion const&, KWin::WindowPaintData const&) () from /usr/lib/libkwin.so.6
#11 0x0000007ff76602e8 in KWin::WorkspaceScene::paintWindow(KWin::RenderTarget const&, KWin::RenderViewport const&, KWin::WindowItem*, int, QRegion const&) () from /usr/lib/libkwin.so.6
#12 0x0000007ff7660660 in KWin::WorkspaceScene::paintSimpleScreen(KWin::RenderTarget const&, KWin::RenderViewport const&, int, QRegion const&) () from /usr/lib/libkwin.so.6
#13 0x0000007ff76600b0 in KWin::WorkspaceScene::paint(KWin::RenderTarget const&, QRegion const&) ()
   from /usr/lib/libkwin.so.6
#14 0x0000007ff76524c0 in KWin::SceneDelegate::paint(KWin::RenderTarget const&, QRegion const&) () from /usr/lib/libkwin.so.6
#15 0x0000007ff7493860 in KWin::Compositor::paintPass(KWin::RenderLayer*, KWin::RenderTarget const&, QRegion const&) ()
   from /usr/lib/libkwin.so.6
#16 0x0000007ff77727dc in KWin::X11Compositor::composite(KWin::RenderLoop*) () from /usr/lib/libkwin.so.6
#17 0x0000007ff42faaa0 in ?? () from /usr/lib/libQt6Core.so.6
#18 0x0000007ff74bfd38 in KWin::RenderLoop::frameRequested(KWin::RenderLoop*) () from /usr/lib/libkwin.so.6
#19 0x0000007ff74c0eac in KWin::RenderLoopPrivate::dispatch() () from /usr/lib/libkwin.so.6
#20 0x0000007ff42faaa0 in ?? () from /usr/lib/libQt6Core.so.6
#21 0x0000007ff430e82c in QTimer::timeout(QTimer::QPrivateSignal) () from /usr/lib/libQt6Core.so.6
#22 0x0000007ff42eb0b8 in QObject::event(QEvent*) () from /usr/lib/libQt6Core.so.6
#23 0x0000007ff544f6d4 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib/libQt6Widgets.so.6
#24 0x0000007ff4281b4c in QCoreApplication::notifyInternal2(QObject*, QEvent*) () from /usr/lib/libQt6Core.so.6
#25 0x0000007ff4470fcc in QTimerInfoList::activateTimers() () from /usr/lib/libQt6Core.so.6
#26 0x0000007ff45c9710 in ?? () from /usr/lib/libQt6Core.so.6
#27 0x0000007ff255af9c in ?? () from /usr/lib/libglib-2.0.so.0

The issue is that xcb_dri3_buffers_from_pixmap_reply is returning NULL with error code 4 (BadPixmap), indicating that the X11 server doesn't recognize the pixmap ID as valid.
Then I used claude to generate a small program to test this function.

// compile with gcc -o dri3_pixmap_test dri3_pixmap_test.c -lxcb -lxcb-dri3
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <xcb/xcb.h>
#include <xcb/dri3.h>
#include <xcb/xcb_aux.h>
#include <xcb/xproto.h>

int main(void) {
    xcb_connection_t *conn;
    xcb_screen_t *screen;
    xcb_pixmap_t pixmap;
    xcb_drawable_t drawable;
    xcb_gcontext_t gc;
    int screen_num;
    xcb_generic_error_t *error;
    
    /* Connect to the X server */
    conn = xcb_connect(NULL, &screen_num);
    if (xcb_connection_has_error(conn)) {
        fprintf(stderr, "Error connecting to X server\n");
        return 1;
    }

    /* Get the screen */
    screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data;
    
    /* Check if DRI3 is available */
    const xcb_query_extension_reply_t *dri3_ext;
    dri3_ext = xcb_get_extension_data(conn, &xcb_dri3_id);
    if (!dri3_ext || !dri3_ext->present) {
        fprintf(stderr, "DRI3 extension not available\n");
        xcb_disconnect(conn);
        return 1;
    }
    
    /* Create a pixmap */
    pixmap = xcb_generate_id(conn);
    xcb_create_pixmap(conn, screen->root_depth, pixmap, screen->root, 256, 256);
    
    /* Create a GC */
    gc = xcb_generate_id(conn);
    xcb_create_gc(conn, gc, pixmap, 0, NULL);
    
    /* Draw something on the pixmap */
    uint32_t values[1] = { screen->white_pixel };
    xcb_change_gc(conn, gc, XCB_GC_FOREGROUND, values);
    xcb_rectangle_t rect = { 0, 0, 256, 256 };
    xcb_poly_fill_rectangle(conn, pixmap, gc, 1, &rect);
    
    /* Try to get buffers from pixmap */
    xcb_dri3_buffers_from_pixmap_cookie_t bfp_cookie;
    xcb_dri3_buffers_from_pixmap_reply_t *bfp_reply;
    
    bfp_cookie = xcb_dri3_buffers_from_pixmap(conn, pixmap);
    bfp_reply = xcb_dri3_buffers_from_pixmap_reply(conn, bfp_cookie, &error);
    
    if (!bfp_reply) {
        if (error) {
            fprintf(stderr, "Error: xcb_dri3_buffers_from_pixmap failed with error code %d\n", 
                    error->error_code);
            free(error);
        } else {
            fprintf(stderr, "Error: xcb_dri3_buffers_from_pixmap failed without error\n");
        }
    } else {
        printf("Success! xcb_dri3_buffers_from_pixmap returned data:\n");
        printf("Width: %d, Height: %d\n", bfp_reply->width, bfp_reply->height);
        printf("Modifier type: %lu\n", (unsigned long)bfp_reply->modifier);
        free(bfp_reply);
    }
    
    /* Clean up */
    xcb_free_gc(conn, gc);
    xcb_free_pixmap(conn, pixmap);
    xcb_disconnect(conn);
    
    return 0;
}

It works on my PC but right returns error in the container on my phone with termux-x11 X server.
Image
Maybe by solving this we can run kwin_x11 normally?
Is it an error in termux-x11's dri3 implementation? Can you help me debug and maybe fix it? Thanks a lot!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions