版本比较

密钥

  • 该行被添加。
  • 该行被删除。
  • 格式已经改变。
目录
minLevel1
maxLevel6
outlinefalse
stylenone
typelist
printablefalse

介绍xorg Server实现框架,引导代码阅读

架构

X11图形系统为C/S架构,Server管理输入输出设备等资源,Client发起请求操作图形等。

  • DDX:设备相关的X实现,包括键盘,鼠标等输入设备,显示等输出设备

  • DIX:设备无关的X实现,包括任务的分发,事件队列,扩展相关实现等

  • Extensions:扩展协议,相对X11核心协议,其增加了client与server之间的交互功能,包括请求和事件

  • Inputs:输入设备包括键盘、鼠标、触控板、触摸屏等

...

https://x.org/wiki/guide/concepts/

源码目录树

介绍关键目录文件功能,除了hw和os相关代码,其它代码可以共享。扩展协议中与硬件相关的实现通过回调函数来抽象,硬件相关代码需实现函数功能。

Name

Explanation

dix/

设备无关部分的代码实现,如:请求的分发和X资源处理

exa/

硬件设备驱动开发框架,xfree86实现依赖该框架

fb/

针对帧缓冲的图形操作实现代码,如:图像的位传输和合成等操作

glamor/

2D和3D图形操作实现,支持OpenEGL硬件渲染

hw/kdrive/ephyr/

嵌套的X11 Server实现,其屏幕输出在X11 Server的一个窗口中

hw/vfb/

虚拟帧缓冲的X11 server实现

hw/xfree86/

X11 server原生实现,运行在类unix操作系统上,如:Linux,BSD等

hw/xnest/

嵌套X11 Server的实现,类似于一个X11代理server

hw/xquartz/

运行在Mac OS X平台上的X11 server实现,

hw/xwayland/

运行在Wayland平台上的X11 server实现

hw/xwin/

运行在window平台上的Cygwin/X 代码

mi/

与机器无关核心协议代码,通过调用screens、windows和graphic contexts等的回调函数来操作调用fb/下的代码

miext/

与机器无关的扩展协议代码,如:SyncFence,Damage等

os/

与硬件无关的操作系统相关代码,如:认证,命令行参数处理等

composite/

composite扩展实现,实现窗口合成功能

damageext/

damage扩展实现,跟踪窗口内容变化区域

dbe/

实现dbe扩展协议,支持窗口的双缓冲功能

dri3/

实现DRI3扩展协议,支持client直接渲染

glx/

实现GLX扩展协议,支持GLX硬件渲染

present/

实现present扩展协议,支持帧缓冲翻页等硬件特性

randr/

实现randr扩展协议,支持缩放,旋转,投射等功能

render/

实现render扩展协议,支持更多的渲染操作,增加了Picture等类型

Xext/

多种扩展协议的实现,如:XvMC,Xv,Xshm,Xfence,Xshape,Xdpms等

xfixes/

Xi/

实现XI2扩展协议,支持多种输入设备功能,如多点触控等

xkb/

实现xkb扩展协议,支持各种键盘设备功能

注:

  1. Xephyr和Xnest实现的功能将被xf86-video-nested驱动代码

  2. Xvfb实现的功能将被xf86-video-dummy驱动代码

xfree86处理流程

Dispatch

任务分发主函数。

代码块
languagecpp

void Dispatch(void){
    // skipped
    while (!dispatchException) {
        if (InputCheckPending()) {
            // 处理输入事件
            ProcessInputEvents();
            // 处理输入事件时产生关键事件等,在此发送
            FlushIfCriticalOutputPending();
        }
        // 阻塞等待,当client请求,输入事件,视频事件等发生时返回
        if (!WaitForSomething(clients_are_ready()))
            continue;
        // client请求处理
        if (!dispatchException && clients_are_ready()) {
            // 分发处理无异常且有client请求,选择其中一个client处理
            client = SmartScheduleClient();
            isItTimeToYield = FALSE;
            start_tick = SmartScheduleTime;
            // client出错,优先级改变,处理事件过长等,都会结束循环
            while (!isItTimeToYield) {
                // 处理键盘,鼠标等输入事件
                if (InputCheckPending())
                    ProcessInputEvents();
                FlushIfCriticalOutputPending();
                // 分时调度,处理单个client时间过长(15ms时间片),降低其优先级,且重新调度
                if ((SmartScheduleTime - start_tick) >= SmartScheduleSlice){
                    if (client->smart_priority > SMART_MIN_PRIORITY)
                        client->smart_priority--;
                    break;
                }
                // 读取client请求信息,返回请求长度,result为0,请求处理完成,进行下一个调度
                result = ReadRequestFromClient(client);
                if (result <= 0) {
                    if (result < 0)
                        CloseDownClient(client);
                    break;
                }
                client->sequence++;
                client->majorOp = ((xReq *) client->requestBuffer)->reqType;
                client->minorOp = 0;
                if (client->majorOp >= EXTENSION_BASE) {
                    // 扩展协议请求,获取扩展协议的操作码minorOp,以区分请求类型
                    ExtensionEntry *ext = GetExtensionEntry(client->majorOp);
                    if (ext)
                        client->minorOp = ext->MinorOpcode(client);
                }
                // 请求长度过大,不符合规范
                if (result > (maxBigRequestSize << 2))
                    result = BadLength;
                else {
                    result = XaceHookDispatch(client, client->majorOp);
                    if (result == Success) {
                        currentClient = client;
                        // 处理请求
                        result = (*client->requestVector[client->majorOp]) (client);
                        currentClient = NULL;
                    }
                }
                // 更新client运行时间,可能使用timer更新事件(SIGALRM)
                if (!SmartScheduleSignalEnable)
                    SmartScheduleTime = GetTimeInMillis();

                if (client->noClientException != Success) {
                    // client异常,关闭该client
                    CloseDownClient(client);
                    break;
                }
                else if (result != Success) {
                    // 处理请求失败,发送错误码给client,如:BadLength
                    SendErrorToClient(client, client->majorOp, client->minorOp, client->errorValue, result);
                    break;
                }
            }
            // 发送请求回复或者事件
            FlushAllOutput();
            if (client == SmartLastClient)
                client->smart_stop_tick = SmartScheduleTime;
        }
        // 若client改变了自己的优先级,则需重新调度client
        dispatchException &= ~DE_PRIORITYCHANGE;
    }
    // server被重置,则进入下一轮运行。server被中断,则退出执行
    KillAllClients();
    dispatchException &= ~DE_RESET;
    SmartScheduleLatencyLimited = 0;
    ResetOsBuffers();
}

WaitForSomething

使用同步多路IO阻塞等待和定时器功能。

代码块
languagecpp
// are_ready是否有输入事件
// 等待和处理定时任务。出错或有事件需处理时返回
Bool WaitForSomething(Bool are_ready){
    // skipped
    timer_is_running = were_ready;
    if (were_ready && !are_ready) {
        // 无输入事件,停止调度定时器
        timer_is_running = FALSE;
        SmartScheduleStopTimer();
    }
    were_ready = FALSE;
    busfault_check();
    while (1) {
        // 执行工作队列中的处理函数
        ProcessWorkQueue();
        // 处理定时任务,返回下次超时时间
        timeout = check_timers();
        // 检查是否有设备的输入事件
        are_ready = clients_are_ready();
        if (are_ready)
            timeout = 0; // 有输入事件等待处理,即时返回
        // 阻塞任务,通过超时处理,可能会修改timeout时间
        BlockHandler(&timeout);
        if (NewOutputPending)
            FlushAllOutput();
        /* keep this check close to select() call to minimize race */
        if (dispatchException)
            i = -1; // 出现异常
        else
            i = ospoll_wait(server_poll, timeout);
        pollerr = GetErrno();
        // 执行操作
        WakeupHandler(i);
        if (i <= 0) {           /* An error or timeout occurred */
            if (dispatchException)
                return FALSE;
            // skipped
        } else
            are_ready = clients_are_ready();
        // 有设备输入事件
        if (InputCheckPending())
            return FALSE;
        if (are_ready) {
            were_ready = TRUE;
            if (!timer_is_running)
                SmartScheduleStartTimer(); // 启动调度计时器,5ms为一个时间片
            return TRUE;
        }
    }
}

client调度机制

采用优先级和分时调度系统来选择client,响应该client的请求。client有两种优先级,静态优先级和动态优先级(smart priority)。优先比较静态优先级,在比较动态优先级。

  • 分时调度的基础时间片为5ms,连续处理一个client超过一个时间片时重新调度client。当长时间只有一个活动client时,动态调整时间片,每1秒钟增加5ms,时间片最大不超过15ms;当有多个活动client时,时间片恢复至5ms。

  • 动态优先级范围为[-20,0],当连续处理client请求超过1个时间片时,动态优先级减一;当连续空间时间超过2个时间片时,动态优先级加一。

代码块
languagecpp
// 选择一个client,处理该client的请求
static ClientPtr SmartScheduleClient(void);

DDX函数

不同功能,运行不同平台上的X11 server,都需重新实现这些函数,接口保持一致。通过预编译宏来选择静态编译X11 server。

初始化屏幕输出

代码块
void InitOutput(ScreenInfo * screen_info, int argc, char **argv);
  • 发现并初始化输出设备,硬件设备或者虚拟设备

  • 初始化ScreenInfo数据结构

初始化屏幕输入

代码块
void InitInput(int argc, char **argv);
  • 发现并初始化输入设备(键盘,鼠标等),硬件设备或者虚拟设备

输入事件处理函数

代码块
void ProcessInputEvents(void);
  • 处理输入事件,InternalEvent类型。这些事件由硬件输入处理模块将硬件事件转换成InternalEvent类型事件,插入到队列中,通过管道方式通知处理。mieqProcessInputEvents封装了通用实现。

  • 一次调用处理队列中所有输入事件

退出server处理函数

代码块
void ddxGiveUp(enum ExitCode error);
  • server退出时调用函数,进行资源回收

屏幕初始化函数

代码块
Bool (*pfnInit) (ScreenPtr pScreen, int argc, char **argv);
  • 初始化屏幕尺寸,分配一个前端帧缓冲(front framebuffer),为每个CRTC分配硬件光标帧缓冲(cursor framebuffer),计算硬件光标尺寸等,设置屏幕的视觉类型(像素深度,色彩格式等)

  • 根据像素深度初始化帧缓冲(framebuffer)的视觉类型(格式和像素深度),初始化屏幕的窗口,pixmap,colormap,图形等处理函数,以及默认值参数。(fbScreenInit)

  • 初始化Screen的图像(picture)处理函数 (fbPictureInit)

  • 初始化屏幕与光标相关的处理函数(machine independent cursor display routines)。初始化光标(xf86PointerScreenFuncs)与屏幕和精灵(miSpritePointerFuncs)相关的处理函数(miDCInitialize)

  • 调用extension协议的ScreenInit回调函数初始化Screen的私有属性,窗口操作、图形操作等回调函数,如:DPMS,Xv,RandR等

如:xf86ScreenInit,xwl_screen_init。

xfree86驱动接口

xfree86驱动接口定义了DDX的输入输出设备驱动接口,驱动以模块(动态库)的形式提供。

代码块
languagecpp
// 加载和卸载模块函数
typedef void *(*ModuleSetupProc) (void *, void *, int *, int *);
typedef void (*ModuleTearDownProc) (void *);

// 模块描述
/* This structure is expected to be returned by the initfunc */
typedef struct {
    const char *modname;        /* name of module, e.g. "foo" */
    const char *vendor;         /* vendor specific string */
    CARD32 _modinfo1_;          /* constant MODINFOSTRING1/2 to find */
    CARD32 _modinfo2_;          /* infoarea with a binary editor or sign tool */
    CARD32 xf86version;         /* contains XF86_VERSION_CURRENT */
    CARD8 majorversion;         /* module-specific major version */
    CARD8 minorversion;         /* module-specific minor version */
    CARD16 patchlevel;          /* module-specific patch level */
    const char *abiclass;       /* ABI class that the module uses */
    CARD32 abiversion;          /* ABI version */
    const char *moduleclass;    /* module class description */
    CARD32 checksum[4];         /* contains a digital signature of the version info structure */
} XF86ModuleVersionInfo;

typedef struct {
    XF86ModuleVersionInfo *vers;
    ModuleSetupProc setup;
    ModuleTearDownProc teardown;
} XF86ModuleData;

typedef Bool xorgDriverFuncProc(ScrnInfoPtr, xorgDriverFuncOp, void *);
// 驱动描述,包括探测函数的实现
typedef struct _DriverRec {
    int driverVersion;
    const char *driverName;
    void (*Identify) (int flags);
    Bool (*Probe) (struct _DriverRec * drv, int flags);
    const OptionInfoRec *(*AvailableOptions) (int chipid, int bustype);
    void *module;
    int refCount;
    xorgDriverFuncProc *driverFunc;

    const struct pci_id_match *supported_devices;
    Bool (*PciProbe) (struct _DriverRec * drv, int entity_num,
                      struct pci_device * dev, intptr_t match_data);
    Bool (*platformProbe) (struct _DriverRec * drv, int entity_num, int flags,
                           struct xf86_platform_device * dev, intptr_t match_data);
} DriverRec, *DriverPtr;

// 注册和卸载驱动函数
void xf86AddDriver(DriverPtr driver, void *module, int flags);
void xf86DeleteDriver(int drvIndex);
  1. 实现模块加载和卸载函数,调用xf86AddDriver和xf86DeleteDriver注册和卸载驱动,及定义模块描述信息

  2. 实现硬件特性查询函数(driverFunc)

  3. 实现获取硬件可用选项的函数(AvailableOptions)(硬件配置)

  4. 实现设备驱动探测函数。共有3种设备探测方式

    1. probe:老版探测设备方法,通过配置文件配置

    2. PciProbe:通过扫描pci设备进行探测设备,使用libpciaccess库实现

    3. platformProbe:通过dbus机制探测设备

    4. xfree86使用udev处理设备热插拔时,udev根据驱动名称加载无需探测函数

xfree86显卡驱动需实现的接口,X11 server提供默认驱动modesetting,其它厂商的显卡在第3方库中,如:xf86-video-amdgpu,xf86-video-intel等。

  1. xfree86通用层实现接口

    1. Probe:探测是否能驱动该设备,目前不再使用该函数进行探测,而是由xfree86驱动实现该功能

    2. PreInit:根据视频硬件设备和配置信息初始化屏幕内容

    3. EnableDisableFBAccess:使能帧缓冲的访问

  2. 驱动独自实现接口

    1. ScreenInit:屏幕初始化接口,DIX层为每个屏幕调用初始化函数

    2. FreeScreen:是否屏幕资源

    3. SwitchMode:切换视频模式

    4. EnterVT:进入控制台,获得控制台的控制权

    5. LeaveVT:离开控制台,释放控制台的控制权

    6. ValidMode:检测特定硬件约束的视频模式

    7. AdjustFrame:更新视口(viewport),如:视口缩放

  3. 扩展协议实现依赖接口:若xfree86 video mode,Xv,randr等扩展协议

代码块
languagecpp
typedef Bool xf86ProbeProc(DriverPtr, int);
typedef Bool xf86PreInitProc(ScrnInfoPtr, int);
typedef Bool xf86ScreenInitProc(ScreenPtr, int, char **);
typedef Bool xf86SwitchModeProc(ScrnInfoPtr, DisplayModePtr);
typedef void xf86AdjustFrameProc(ScrnInfoPtr, int, int);
typedef Bool xf86EnterVTProc(ScrnInfoPtr);
typedef void xf86LeaveVTProc(ScrnInfoPtr);
typedef void xf86FreeScreenProc(ScrnInfoPtr);
typedef ModeStatus xf86ValidModeProc(ScrnInfoPtr, DisplayModePtr, Bool, int);
typedef void xf86EnableDisableFBAccessProc(ScrnInfoPtr, Bool);
typedef int xf86SetDGAModeProc(ScrnInfoPtr, int, DGADevicePtr);
typedef int xf86ChangeGammaProc(ScrnInfoPtr, Gamma);
typedef void xf86PointerMovedProc(ScrnInfoPtr, int, int);
typedef Bool xf86PMEventProc(ScrnInfoPtr, pmEvent, Bool);
typedef void xf86DPMSSetProc(ScrnInfoPtr, int, int);
typedef void xf86LoadPaletteProc(ScrnInfoPtr, int, int *, LOCO *, VisualPtr);
typedef void xf86SetOverscanProc(ScrnInfoPtr, int);
typedef void xf86ModeSetProc(ScrnInfoPtr);

https://www.x.org/releases/current/doc/xorg-server/ddxDesign.html

Extensions代码框架

扩展协议组件一般可以组件方式存在,通过配置来加载和初始化扩展协议,一般使静态加载。

代码块
languagecpp
// 扩展协议注册接口
extern _X_EXPORT ExtensionEntry *
AddExtension(const char * /*name */ ,
             int /*NumEvents */ ,
             int /*NumErrors */ ,
             int (* /*MainProc */ )(ClientPtr /*client */ ),
             int (* /*SwappedMainProc */ )(ClientPtr /*client */ ),
             void (* /*CloseDownProc */ )(ExtensionEntry * /*extension */ ),
             unsigned short (* /*MinorOpcodeProc */ )(ClientPtr /*client */ )
    );

// 扩展初始化函数,主要需注册扩展协议的请求和事件
typedef void (*InitExtension) (void);

// 扩展协议描述结构
typedef struct {
    InitExtension initFunc; // 初始化函数地址
    const char *name;       // 扩展协议名称
    Bool *disablePtr;       // 是否禁用该协议,可动态指定
} ExtensionModule;
  1. NumEvents:定义事件数量,可以没有

  2. NumErrors:定义错误编号数量,可以没有

  3. MainProc:请求处理函数

  4. SwappedMainProc:请求处理函数,与client端的字节序相反时,调用该处理函数

  5. CloseDownProc:清理函数,一般为空

  6. MinorOpcodeProc:次操作码处理,X11协议中有个次操作码,扩展协议可根据需要进行转换。

  7. InitExtension:实现初始化函数,注册资源类型,定义扩展私有属性,封装屏幕回调函数,调用AddExtension注册扩展协议等

注:扩展协议全局的事件编号和请求编号在server启动时确定。

  • X11 server对每个扩展协议分配一个请求操作码,扩展协议的起始请求操作码从128其,128以下的请求码为核心协议的请求。

  • X11 server对扩展协议的事件编号,起始编号为64,扩展协议初始化顺序累计编号,总数不能超过64个。

事件处理机制

所有事件在主流程中处理,使用操作系统poll机制的同步多路IO响应IO事件。

代码块
languagecpp
// fd:文件句柄,如:socket,dbus,device,netlink,udev monitor,drm等
// notify:事件处理函数
// mask:请求事件,如:读或写;为0时表示注销
// data:传递给事件处理函数参数
Bool SetNotifyFd(int fd, NotifyFdProcPtr notify, int mask, void *data);

// fd:同上
// ready:响应事件(X_NOTIFY_READ、X_NOTIFY_READ或X_NOTIFY_ERROR)
// data:同上
typedef void (*NotifyFdProcPtr)(int fd, int ready, void *data);

// xfree86注册函数
typedef void (*InputHandlerProc) (int fd, void *data);
// 输入设备IO处理函数
void *xf86AddInputHandler(int fd, InputHandlerProc proc, void *data);
// 其它设备处理函数,如:显示器差别,电源管理等
void *xf86AddGeneralHandler(int fd, InputHandlerProc proc, void *data);

// 回复请求或者发送事件
void FlushAllOutput(void);

各类IO事件注册和处理函数列表,均在主线程上下文处理。

注册函数

处理函数

文件或句柄

说明

SetNotifyFd

EstablishNewConnections

/tmp/.X11-unix/X0

server监听client连接

ospoll_add

ClientReady

client connection

监听client请求

SetNotifyFd

ms_drm_socket_handler

dev/dri/card0

drm事件处理

SetNotifyFd

xf86ReadInput

input device fd

响应输入设备IO

SetNotifyFd

socket_handler

udev monitor netlink

设备热插拔

SetNotifyFd

socket_handler

DBUS_BUS_SYSTEM

设备暂停或恢复

xf86AddGeneralHandler

drmmode_handle_uevents

udev monitor netlink

显示器插拔

xf86AddGeneralHandler

xf86HandlePMEvents

/var/run/acpid.socket

ACPI电源管理

输入设备事件

为了快速响应输入设备事件,xorg server使用一个专门线程响应输入事件,并将输入事件转换为InternalEvent类型事件,插入输入事件队列中,再交由主线程处理输入事件。

代码块
languagecpp
// 输入线程管理的设备队列
static InputThreadInfo *inputThreadInfo;
// 新增设备,将设备加入队列中,并通知IO线程处理新设备
void xf86AddEnabledDevice(InputInfoPtr pInfo){
    InputThreadRegisterDev(pInfo->fd, xf86ReadInput, pInfo);
}

// 输入设备IO线程处理函数
static void *InputThreadDoWork(void *arg);

// InternalEvent事件循环队列,可动态加减
static EventQueueRec miEventQueue;
// 事件插入队列函数
void mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e);

定义了两个pipe队列:hotplug和read/write

  • 主线程监听到设备的热插拔,对设备处理后,通过写入hotplug一个字节数据通知IO线程响应设备IO事件,IO线程监听新增设备IO事件(InputReady)

  • 主线程监听read/write队列的读事件,当IO线程收到输入设备IO事件后,将IO事件转换成InternalEvent事件,并插入miEventQueue循环队列中,向read/write队列写一个字节数据通知主线程,主线程调用ProcessInputEvents函数处理事件。

两个线程共享队列数据接口,采用了一把锁进行互斥,在队列操作,输入设备操作等都加锁了。IO事件处理的互斥操作会影响交互性能。

注:xwayland未使用单独线程处理IO事件

https://x.org/wiki/Development/Documentation/InputEventProcessing/

设备管理

  • xserver的xfree86实现使用udev机制发现设备,注册udev的socket_handler处理函数。

    • NewGPUDeviceRequest / DeleteGPUDeviceRequest:处理插入或拔出的drm GPU设备

    • NewInputDeviceRequest / remove_devices:处理插入或拔出的输入设备

  • 使用udev显示器的热插拔,modesetting驱动注册drmmode_handle_uevents处理函数

  • 采用dbus的system-logind处理设备的暂停与恢复,注册dbus的socket_handler处理函数,使用system-logind的message_filter响应dbus的设备暂停或恢复消息。

注:均在主线程中使用同步多路IO响应事件。

工作队列

工作队列中的请求,在每次处理轮回中执行,共有注册了四个处理函数:

  • compScreenUpdate:将子窗口内容绘制父窗口中

  • compRepaintBorder:重绘窗口边框

  • xf86libinput_hotplug_device_cb:设备插拔,处理子设备的初始化(libinput)

  • update_mode_prop_cb:设备状态更新(libinput)

代码块
// 工作队列
WorkQueuePtr workQueue;

// 注册处理函数至工作队列
// function:处理函数
// closure:传递给处理函数参数
Bool QueueWorkProc(Bool (*function) (ClientPtr pClient, void *closure), ClientPtr client, void *closure);

// 执行工作队列处理函数,处理请求事件后调用
void ProcessWorkQueue(void);

回调链表

某些状态、动作、发生时,扩展协议或平台的实现需要对这些事件进行处理。如:属性,状态等发生变化

名称

处理函数

执行时机

ClientStateCallback

RRClientCallback

client状态变化时调用

RootWindowFinalizeCallback

AddVTAtoms

AddSeatId

addEDIDProp

xwl_root_window_finalized_callback

创建根窗口后调用

PropertyStateCallback

xwl_property_callback

窗口属性发生变化时调用

SelectionCallback

wm_selection_callback

XFixesSelectionCallback

client发起select操作时调用

ResourceStateCallback

SELinuxResourceState

资源状态发生改变时调用

miCallbacksWhenDrained

N/A

此轮输入事件处理完成后调用

阻塞唤醒处理函数

阻塞函数(BlockHandler)是在epoll等待事件之前执行的函数,唤醒函数(WakeupHandler)是在epoll等待之后调用。有的扩展协议使用该方式实现定时器功能,在阻塞函数中计算超时事件,在唤醒函数中检查条件,满足时执行任务,如SyncCounter的实现。这些任务是临时性的,执行一次之后可不再执行(回调函数清空)。

代码块
// 在epoll之前调用所有的Server和Screen的BlockHandler,可能会调整pTimeout的值
void BlockHandler(void *pTimeout);
// 在epoll之后调用所有的Server和Screen的WakeupHandler
// result:小于0表示出错;等于0表示超时;大于0表示epoll时间数。
void WakeupHandler(int result);

// timeout下次超时时间,BlockHandler回调函数可能会更新timeout时间
// result:<0 - error;=0 - timeout;>0 - activity(poll事件数)
// 屏幕相关的处理函数
typedef void (*ScreenBlockHandlerProcPtr) (ScreenPtr pScreen, void *timeout);
typedef void (*ScreenWakeupHandlerProcPtr) (ScreenPtr pScreen, int result);

// 系统(server)相关的处理函数
static BlockHandlerPtr handlers;
typedef void (*ServerBlockHandlerProcPtr) (void *blockData, void *timeout);
typedef void (*ServerWakeupHandlerProcPtr) (void *blockData, int result);
Bool RegisterBlockAndWakeupHandlers(ServerBlockHandlerProcPtr blockHandler,
                               ServerWakeupHandlerProcP tr wakeupHandler,
                               void *blockData);

系统处理函数

调用RegisterBlockAndWakeupHandlers动态注册阻塞唤醒函数,插入到handlers队列中。

BlockHandler

WakeupHandler

description

IdleTimeBlockHandler

IdleTimeWakeupHandler

SyncCounter的实现,定时执行任务

DRIBlockHandler

DRIWakeupHandler

DRI1相关实现,已淘汰

fs_block_handler

FontWakeup

字体相关操作

block_handler

wakeup_handler

xwayland发送所有请求给Wayland server

N/A

xf86Wakeup

进入图形界面相关操作

屏幕处理函数

与Screen相关的处理函数,以下函数封装成函数链,调用Screen的BlockHandler和WakeupHandler回调函数即可。

BlockHandler

WakeupHandler

description

DRIDoBlockHandler

DRIDoWakeupHandler

DRI1相关实现,已淘汰

ExaBlockHandler

ExaWakeupHandler

与exa驱动框架相关,已淘汰

_glamor_block_handler

N/A

执行挂起(未处理)的渲染请求

miSpriteBlockHandler

N/A

显示不再帧缓冲的光标

msBlockHandler

N/A

处理屏幕显示相关操作

xf86RotateBlockHandler

N/A

处理屏幕旋转