首页 > 其他分享 >dotnet X11 多次调用 XPutImage 是否能做到渲染同步

dotnet X11 多次调用 XPutImage 是否能做到渲染同步

时间:2024-08-24 09:09:28浏览次数:5  
标签:img display var XPutImage dotnet X11 event ExposeEvent

本文将告诉大家我在麒麟系统和统信系统以及分别搭配飞腾和兆芯处理器的设备上,使用连续的 XPutImage 方法推送界面,测试是否能够在一次渲染内完成。测试结论是不能做到渲染同步

本文的核心测试代码如下

        XPutImage(display, handle, gc, ref xImage, @event.ExposeEvent.x, @event.ExposeEvent.y, @event.ExposeEvent.x, @event.ExposeEvent.y, (uint) @event.ExposeEvent.width,
            (uint) @event.ExposeEvent.height);

        XPutImage(display, handle, gc, ref halfImage, 0, 0, halfWidth, 0, (uint) halfWidth,
            (uint) height);

即连续调用两次 XPutImage 方法,其中最后一次的 XPutImage 方法是让右半边覆盖掉。如果渲染能对齐同步的话,预期右半边是不会出现闪烁问题,即不会出现先在屏幕显示首个 XPutImage 绘制的全窗口图片,再显示回最后一次的 XPutImage 覆盖的画面

然而经过实际测试,窗口显示的内容将会闪烁,即连续两次 XPutImage 不能做到渲染同步,这也符合阅读 XLib 和 XServer 和 KWin 的代码了解的行为

全部的测试代码如下

using CPF.Linux;

using SkiaSharp;

using static CPF.Linux.XLib;

XInitThreads();
var display = XOpenDisplay(IntPtr.Zero);
var screen = XDefaultScreen(display);
var rootWindow = XDefaultRootWindow(display);

XMatchVisualInfo(display, screen, 32, 4, out var info);
var visual = info.visual;

var valueMask =
        //SetWindowValuemask.BackPixmap
        0
        | SetWindowValuemask.BackPixel
        | SetWindowValuemask.BorderPixel
        | SetWindowValuemask.BitGravity
        | SetWindowValuemask.WinGravity
        | SetWindowValuemask.BackingStore
        | SetWindowValuemask.ColorMap
    //| SetWindowValuemask.OverrideRedirect
    ;
var xSetWindowAttributes = new XSetWindowAttributes
{
    backing_store = 1,
    bit_gravity = Gravity.NorthWestGravity,
    win_gravity = Gravity.NorthWestGravity,
    //override_redirect = true, // 设置窗口的override_redirect属性为True,以避免窗口管理器的干预
    colormap = XCreateColormap(display, rootWindow, visual, 0),
    border_pixel = 0,
    background_pixel = 0,
};

var xDisplayWidth = XDisplayWidth(display, screen);
var xDisplayHeight = XDisplayHeight(display, screen);

var width = xDisplayWidth;
var height = xDisplayHeight;

var handle = XCreateWindow(display, rootWindow, 0, 0, width, height, 5,
    32,
    (int) CreateWindowArgs.InputOutput,
    visual,
    (nuint) valueMask, ref xSetWindowAttributes);

XEventMask ignoredMask = XEventMask.SubstructureRedirectMask | XEventMask.ResizeRedirectMask |
                         XEventMask.PointerMotionHintMask;
var mask = new IntPtr(0xffffff ^ (int) ignoredMask);
XSelectInput(display, handle, mask);

XMapWindow(display, handle);
XFlush(display);

var gc = XCreateGC(display, handle, 0, 0);
var skBitmap = new SKBitmap(width, height, SKColorType.Bgra8888, SKAlphaType.Premul);
var skCanvas = new SKCanvas(skBitmap);
var xImage = CreateImage(skBitmap);

skCanvas.Clear(SKColors.Blue);
skCanvas.Flush();

var halfWidth = width / 2;
var halfSkBitmap = new SKBitmap(halfWidth, height, SKColorType.Bgra8888, SKAlphaType.Premul);
var halfSkCanvas = new SKCanvas(halfSkBitmap);
halfSkCanvas.Clear();
halfSkCanvas.Flush();
var halfImage = CreateImage(halfSkBitmap);

_ = Task.Run(() =>
{
    var newDisplay = XOpenDisplay(IntPtr.Zero);

    while (true)
    {
        Console.ReadLine();

        var xEvent = new XEvent
        {
            ExposeEvent =
            {
                type = XEventName.Expose,
                send_event = true,
                window = handle,
                count = 1,
                display = newDisplay,
                x = 0,
                y = 0,
                width = width,
                height = height,
            }
        };
        // [Xlib Programming Manual: Expose Events](https://tronche.com/gui/x/xlib/events/exposure/expose.html )
        XLib.XSendEvent(newDisplay, handle, propagate: false,
            new IntPtr((int) (EventMask.ExposureMask)),
            ref xEvent);
        
        XFlush(newDisplay);
    }

    XCloseDisplay(newDisplay);
});

while (true)
{
    var xNextEvent = XNextEvent(display, out var @event);

    if (xNextEvent != 0)
    {
        break;
    }

    if (@event.type == XEventName.Expose)
    {
        skCanvas.Clear(new SKColor((uint)Random.Shared.Next()).WithAlpha(0xFF));
        skCanvas.Flush();

        XPutImage(display, handle, gc, ref xImage, @event.ExposeEvent.x, @event.ExposeEvent.y, @event.ExposeEvent.x, @event.ExposeEvent.y, (uint) @event.ExposeEvent.width,
            (uint) @event.ExposeEvent.height);

        XPutImage(display, handle, gc, ref halfImage, 0, 0, halfWidth, 0, (uint) halfWidth,
            (uint) height);
        XFlush(display);
    }
}

static XImage CreateImage(SKBitmap skBitmap)
{
    const int bytePerPixelCount = 4; // RGBA 一共4个 byte 长度
    var bitPerByte = 8;

    var bitmapWidth = skBitmap.Width;
    var bitmapHeight = skBitmap.Height;

    var img = new XImage();
    int bitsPerPixel = bytePerPixelCount * bitPerByte;
    img.width = bitmapWidth;
    img.height = bitmapHeight;
    img.format = 2; //ZPixmap;
    img.data = skBitmap.GetPixels();
    img.byte_order = 0; // LSBFirst;
    img.bitmap_unit = bitsPerPixel;
    img.bitmap_bit_order = 0; // LSBFirst;
    img.bitmap_pad = bitsPerPixel;
    img.depth = bitsPerPixel;
    img.bytes_per_line = bitmapWidth * bytePerPixelCount;
    img.bits_per_pixel = bitsPerPixel;
    XInitImage(ref img);

    return img;
}

本文代码放在 githubgitee 上,可以使用如下命令行拉取代码。我整个代码仓库比较庞大,使用以下命令行可以进行部分拉取,拉取速度比较快

先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码

git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin b54f37030aec86fda474e99c0ad9ae941e23e1da

以上使用的是国内的 gitee 的源,如果 gitee 不能访问,请替换为 github 的源。请在命令行继续输入以下代码,将 gitee 源换成 github 源进行拉取代码。如果依然拉取不到代码,可以发邮件向我要代码

git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
git pull origin b54f37030aec86fda474e99c0ad9ae941e23e1da

获取代码之后,进入 X11/ChihewigiKurwawhalcelfe 文件夹,即可获取到源代码

更多技术博客,请参阅 博客导航

标签:img,display,var,XPutImage,dotnet,X11,event,ExposeEvent
From: https://www.cnblogs.com/lindexi/p/18377330

相关文章

  • dotnet C# 结构体出方法弹栈之后的行为
    本文记录我在.NET9里测试的行为,在方法里面创建的在栈上的结构体,在方法执行结束之后,栈上的结构体将会被弹栈进入不受管理区域,此时的结构体内存内容不会立刻被清空或被改写这是我在对dotnetX11栈空间被回收导致调用XPutShmImage闪退博客的内容进行更多的测试,确保和X11没......
  • QTabWidget自定义样式(仿DotNetBar)
    QSS如下,若需要tab栏背景色需要添加ui->tabWidget->setAttribute(Qt::WA_StyledBackground);语句使background-color生效,这个时候qtdesigner中仍然看不到背景色,但是不要担心它是生效的,只需在属性中勾上autofillbackground即可在designer中预览(该属性在QWidget属性组中,实际上勾不勾......
  • Docker+Win11:显示Docker中的GUI,解决报错“[Open3D WARNING] GLFW Error: X11: Failed
        在本系列博文中,我将Pytorch部署在Win11为宿主的Docker中,并成功的调用GPU进行了训练。这为我提供了很多便利。    今天在进行3D相关的深度学习研究时我遇到了一些问题:[Open3DWARNING]GLFWError:X11:Failedtoopendisplay:0[Open3DWARNING]Faile......
  • 解决“往日不再”DX11错误的全面指南:探究原因与提供实用解决方案
    《往日不再》(DaysGone)是一款由BendStudio开发、SonyInteractiveEntertainment发行的末世生存动作冒险游戏。该游戏最初为PlayStation4平台独占,后移植到PC平台,让更多的玩家能够体验其扣人心弦的故事和紧张刺激的游戏玩法。然而,在PC平台上运行时,部分玩家可能会遇到DirectX1......
  • dotnet hello world
    参考资料dotnet命令参考使用dotnettest和xUnit在.NET中对C#进行单元测试DeclaringInternalsVisibleTointhecsprojXUnit输出消息创建控制台项目#创建项目目录mdDotnetStudycdDotnetStudy#创建解决方案dotnetnewsln#创建控制台项目,-n:名称,--use......
  • ubuntu安装x11vnc,xauth: unable to generate an authority file name
    ubuntu安装x11vnc,xauth:unabletogenerateanauthorityfilename在Ubuntu上安装和配置x11vnc时,如果遇到“xauth:unabletogenerateanauthorityfilename”的错误,通常是由于权限问题或缺少必要的环境变量引起的。以下是一些解决此问题的步骤:安装x11vnc首......
  • 关于ssh的X11Forwarding功能和vnc端口冲突的问题
    前言偶然间发现有时vnc端口启动不了,显示端口已经启动,但是查看发现默认的59xx端口未启动,但是60xx端口缺被一个sshd进程占用,vnc服务除了默认的59xx端口,还会用到60xx端口。正是因为这个60xx端口被sshd进程占用,所以vnc才启动不了。 那么这个sshd端口是干嘛的呢,默认的sshd端口不是......
  • zig vs c++:控制x11鼠标移动
    zigDebug输出大小:2.3MBReleaseSmall输出大小:11.3kBconststd=@import("std");constx11=@cImport({@cInclude("X11/Xlib.h");});//Convertsbetweennumerictypes:.Enum,.Intand.Float.pubinlinefnas(comptimeT:type,from:anyty......
  • 如何在带有DX11绘图界面的软件上画imgui界面
    前言处于某些研究目的,我们经常需要在dx11绘制的界面上绘制我们自己的操作菜单,以方便进行一些可视化操作;这里面imgui库因为其优越的可用性,健壮性和美观性,得到了很多人的青睐。那么我们应该如何在一个带有dx的软件界面上利用imgui绘制我们自己的界面呢?下面的代码就是为了解决这个问......
  • WCHNET_SocketSend返回0x11原因及解决方法
    问题描述:TCPCLIENT模式使用WCHNET_SocketSend发送有概率会返回0x11按wchnet.h定义为内存溢出错误。异常分析:通过WCHNET_QueryUnack查看,发现异常时发送队列或缓冲区已经占满,导致再次发送时报发送内存溢出错误。 解决方法:如果项目对RAM需求不大,可适当将WCHNET_NUM_TCP_SE......