目录

介绍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

任务分发主函数。

1 2void Dispatch(void){ 3 // skipped 4 while (!dispatchException) { 5 if (InputCheckPending()) { 6 // 处理输入事件 7 ProcessInputEvents(); 8 // 处理输入事件时产生关键事件等,在此发送 9 FlushIfCriticalOutputPending(); 10 } 11 // 阻塞等待,当client请求,输入事件,视频事件等发生时返回 12 if (!WaitForSomething(clients_are_ready())) 13 continue; 14 // client请求处理 15 if (!dispatchException && clients_are_ready()) { 16 // 分发处理无异常且有client请求,选择其中一个client处理 17 client = SmartScheduleClient(); 18 isItTimeToYield = FALSE; 19 start_tick = SmartScheduleTime; 20 // client出错,优先级改变,处理事件过长等,都会结束循环 21 while (!isItTimeToYield) { 22 // 处理键盘,鼠标等输入事件 23 if (InputCheckPending()) 24 ProcessInputEvents(); 25 FlushIfCriticalOutputPending(); 26 // 分时调度,处理单个client时间过长(15ms时间片),降低其优先级,且重新调度 27 if ((SmartScheduleTime - start_tick) >= SmartScheduleSlice){ 28 if (client->smart_priority > SMART_MIN_PRIORITY) 29 client->smart_priority--; 30 break; 31 } 32 // 读取client请求信息,返回请求长度,result为0,请求处理完成,进行下一个调度 33 result = ReadRequestFromClient(client); 34 if (result <= 0) { 35 if (result < 0) 36 CloseDownClient(client); 37 break; 38 } 39 client->sequence++; 40 client->majorOp = ((xReq *) client->requestBuffer)->reqType; 41 client->minorOp = 0; 42 if (client->majorOp >= EXTENSION_BASE) { 43 // 扩展协议请求,获取扩展协议的操作码minorOp,以区分请求类型 44 ExtensionEntry *ext = GetExtensionEntry(client->majorOp); 45 if (ext) 46 client->minorOp = ext->MinorOpcode(client); 47 } 48 // 请求长度过大,不符合规范 49 if (result > (maxBigRequestSize << 2)) 50 result = BadLength; 51 else { 52 result = XaceHookDispatch(client, client->majorOp); 53 if (result == Success) { 54 currentClient = client; 55 // 处理请求 56 result = (*client->requestVector[client->majorOp]) (client); 57 currentClient = NULL; 58 } 59 } 60 // 更新client运行时间,可能使用timer更新事件(SIGALRM) 61 if (!SmartScheduleSignalEnable) 62 SmartScheduleTime = GetTimeInMillis(); 63 64 if (client->noClientException != Success) { 65 // client异常,关闭该client 66 CloseDownClient(client); 67 break; 68 } 69 else if (result != Success) { 70 // 处理请求失败,发送错误码给client,如:BadLength 71 SendErrorToClient(client, client->majorOp, client->minorOp, client->errorValue, result); 72 break; 73 } 74 } 75 // 发送请求回复或者事件 76 FlushAllOutput(); 77 if (client == SmartLastClient) 78 client->smart_stop_tick = SmartScheduleTime; 79 } 80 // 若client改变了自己的优先级,则需重新调度client 81 dispatchException &= ~DE_PRIORITYCHANGE; 82 } 83 // server被重置,则进入下一轮运行。server被中断,则退出执行 84 KillAllClients(); 85 dispatchException &= ~DE_RESET; 86 SmartScheduleLatencyLimited = 0; 87 ResetOsBuffers(); 88}

WaitForSomething

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

1// are_ready是否有输入事件 2// 等待和处理定时任务。出错或有事件需处理时返回 3Bool WaitForSomething(Bool are_ready){ 4 // skipped 5 timer_is_running = were_ready; 6 if (were_ready && !are_ready) { 7 // 无输入事件,停止调度定时器 8 timer_is_running = FALSE; 9 SmartScheduleStopTimer(); 10 } 11 were_ready = FALSE; 12 busfault_check(); 13 while (1) { 14 // 执行工作队列中的处理函数 15 ProcessWorkQueue(); 16 // 处理定时任务,返回下次超时时间 17 timeout = check_timers(); 18 // 检查是否有设备的输入事件 19 are_ready = clients_are_ready(); 20 if (are_ready) 21 timeout = 0; // 有输入事件等待处理,即时返回 22 // 阻塞任务,通过超时处理,可能会修改timeout时间 23 BlockHandler(&timeout); 24 if (NewOutputPending) 25 FlushAllOutput(); 26 /* keep this check close to select() call to minimize race */ 27 if (dispatchException) 28 i = -1; // 出现异常 29 else 30 i = ospoll_wait(server_poll, timeout); 31 pollerr = GetErrno(); 32 // 执行操作 33 WakeupHandler(i); 34 if (i <= 0) { /* An error or timeout occurred */ 35 if (dispatchException) 36 return FALSE; 37 // skipped 38 } else 39 are_ready = clients_are_ready(); 40 // 有设备输入事件 41 if (InputCheckPending()) 42 return FALSE; 43 if (are_ready) { 44 were_ready = TRUE; 45 if (!timer_is_running) 46 SmartScheduleStartTimer(); // 启动调度计时器,5ms为一个时间片 47 return TRUE; 48 } 49 } 50}

client调度机制

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

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

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

1// 选择一个client,处理该client的请求 2static ClientPtr SmartScheduleClient(void);

DDX函数

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

初始化屏幕输出

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

  • 初始化ScreenInfo数据结构

初始化屏幕输入

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

输入事件处理函数

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

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

退出server处理函数

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

屏幕初始化函数

1Bool (*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的输入输出设备驱动接口,驱动以模块(动态库)的形式提供。

1// 加载和卸载模块函数 2typedef void *(*ModuleSetupProc) (void *, void *, int *, int *); 3typedef void (*ModuleTearDownProc) (void *); 4 5// 模块描述 6/* This structure is expected to be returned by the initfunc */ 7typedef struct { 8 const char *modname; /* name of module, e.g. "foo" */ 9 const char *vendor; /* vendor specific string */ 10 CARD32 _modinfo1_; /* constant MODINFOSTRING1/2 to find */ 11 CARD32 _modinfo2_; /* infoarea with a binary editor or sign tool */ 12 CARD32 xf86version; /* contains XF86_VERSION_CURRENT */ 13 CARD8 majorversion; /* module-specific major version */ 14 CARD8 minorversion; /* module-specific minor version */ 15 CARD16 patchlevel; /* module-specific patch level */ 16 const char *abiclass; /* ABI class that the module uses */ 17 CARD32 abiversion; /* ABI version */ 18 const char *moduleclass; /* module class description */ 19 CARD32 checksum[4]; /* contains a digital signature of the version info structure */ 20} XF86ModuleVersionInfo; 21 22typedef struct { 23 XF86ModuleVersionInfo *vers; 24 ModuleSetupProc setup; 25 ModuleTearDownProc teardown; 26} XF86ModuleData; 27 28typedef Bool xorgDriverFuncProc(ScrnInfoPtr, xorgDriverFuncOp, void *); 29// 驱动描述,包括探测函数的实现 30typedef struct _DriverRec { 31 int driverVersion; 32 const char *driverName; 33 void (*Identify) (int flags); 34 Bool (*Probe) (struct _DriverRec * drv, int flags); 35 const OptionInfoRec *(*AvailableOptions) (int chipid, int bustype); 36 void *module; 37 int refCount; 38 xorgDriverFuncProc *driverFunc; 39 40 const struct pci_id_match *supported_devices; 41 Bool (*PciProbe) (struct _DriverRec * drv, int entity_num, 42 struct pci_device * dev, intptr_t match_data); 43 Bool (*platformProbe) (struct _DriverRec * drv, int entity_num, int flags, 44 struct xf86_platform_device * dev, intptr_t match_data); 45} DriverRec, *DriverPtr; 46 47// 注册和卸载驱动函数 48void xf86AddDriver(DriverPtr driver, void *module, int flags); 49void 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等扩展协议

1typedef Bool xf86ProbeProc(DriverPtr, int); 2typedef Bool xf86PreInitProc(ScrnInfoPtr, int); 3typedef Bool xf86ScreenInitProc(ScreenPtr, int, char **); 4typedef Bool xf86SwitchModeProc(ScrnInfoPtr, DisplayModePtr); 5typedef void xf86AdjustFrameProc(ScrnInfoPtr, int, int); 6typedef Bool xf86EnterVTProc(ScrnInfoPtr); 7typedef void xf86LeaveVTProc(ScrnInfoPtr); 8typedef void xf86FreeScreenProc(ScrnInfoPtr); 9typedef ModeStatus xf86ValidModeProc(ScrnInfoPtr, DisplayModePtr, Bool, int); 10typedef void xf86EnableDisableFBAccessProc(ScrnInfoPtr, Bool); 11typedef int xf86SetDGAModeProc(ScrnInfoPtr, int, DGADevicePtr); 12typedef int xf86ChangeGammaProc(ScrnInfoPtr, Gamma); 13typedef void xf86PointerMovedProc(ScrnInfoPtr, int, int); 14typedef Bool xf86PMEventProc(ScrnInfoPtr, pmEvent, Bool); 15typedef void xf86DPMSSetProc(ScrnInfoPtr, int, int); 16typedef void xf86LoadPaletteProc(ScrnInfoPtr, int, int *, LOCO *, VisualPtr); 17typedef void xf86SetOverscanProc(ScrnInfoPtr, int); 18typedef void xf86ModeSetProc(ScrnInfoPtr);

Extensions代码框架

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

1// 扩展协议注册接口 2extern _X_EXPORT ExtensionEntry * 3AddExtension(const char * /*name */ , 4 int /*NumEvents */ , 5 int /*NumErrors */ , 6 int (* /*MainProc */ )(ClientPtr /*client */ ), 7 int (* /*SwappedMainProc */ )(ClientPtr /*client */ ), 8 void (* /*CloseDownProc */ )(ExtensionEntry * /*extension */ ), 9 unsigned short (* /*MinorOpcodeProc */ )(ClientPtr /*client */ ) 10 ); 11 12// 扩展初始化函数,主要需注册扩展协议的请求和事件 13typedef void (*InitExtension) (void); 14 15// 扩展协议描述结构 16typedef struct { 17 InitExtension initFunc; // 初始化函数地址 18 const char *name; // 扩展协议名称 19 Bool *disablePtr; // 是否禁用该协议,可动态指定 20} 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事件。

1// fd:文件句柄,如:socket,dbus,device,netlink,udev monitor,drm等 2// notify:事件处理函数 3// mask:请求事件,如:读或写;为0时表示注销 4// data:传递给事件处理函数参数 5Bool SetNotifyFd(int fd, NotifyFdProcPtr notify, int mask, void *data); 6 7// fd:同上 8// ready:响应事件(X_NOTIFY_READ、X_NOTIFY_READ或X_NOTIFY_ERROR) 9// data:同上 10typedef void (*NotifyFdProcPtr)(int fd, int ready, void *data); 11 12// xfree86注册函数 13typedef void (*InputHandlerProc) (int fd, void *data); 14// 输入设备IO处理函数 15void *xf86AddInputHandler(int fd, InputHandlerProc proc, void *data); 16// 其它设备处理函数,如:显示器差别,电源管理等 17void *xf86AddGeneralHandler(int fd, InputHandlerProc proc, void *data); 18 19// 回复请求或者发送事件 20void 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类型事件,插入输入事件队列中,再交由主线程处理输入事件。

1// 输入线程管理的设备队列 2static InputThreadInfo *inputThreadInfo; 3// 新增设备,将设备加入队列中,并通知IO线程处理新设备 4void xf86AddEnabledDevice(InputInfoPtr pInfo){ 5 InputThreadRegisterDev(pInfo->fd, xf86ReadInput, pInfo); 6} 7 8// 输入设备IO线程处理函数 9static void *InputThreadDoWork(void *arg); 10 11// InternalEvent事件循环队列,可动态加减 12static EventQueueRec miEventQueue; 13// 事件插入队列函数 14void 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事件

设备管理

  • 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)

1// 工作队列 2WorkQueuePtr workQueue; 3 4// 注册处理函数至工作队列 5// function:处理函数 6// closure:传递给处理函数参数 7Bool QueueWorkProc(Bool (*function) (ClientPtr pClient, void *closure), ClientPtr client, void *closure); 8 9// 执行工作队列处理函数,处理请求事件后调用 10void 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的实现。这些任务是临时性的,执行一次之后可不再执行(回调函数清空)。

1// 在epoll之前调用所有的Server和Screen的BlockHandler,可能会调整pTimeout的值 2void BlockHandler(void *pTimeout); 3// 在epoll之后调用所有的Server和Screen的WakeupHandler 4// result:小于0表示出错;等于0表示超时;大于0表示epoll时间数。 5void WakeupHandler(int result); 6 7// timeout下次超时时间,BlockHandler回调函数可能会更新timeout时间 8// result:<0 - error;=0 - timeout;>0 - activity(poll事件数) 9// 屏幕相关的处理函数 10typedef void (*ScreenBlockHandlerProcPtr) (ScreenPtr pScreen, void *timeout); 11typedef void (*ScreenWakeupHandlerProcPtr) (ScreenPtr pScreen, int result); 12 13// 系统(server)相关的处理函数 14static BlockHandlerPtr handlers; 15typedef void (*ServerBlockHandlerProcPtr) (void *blockData, void *timeout); 16typedef void (*ServerWakeupHandlerProcPtr) (void *blockData, int result); 17Bool RegisterBlockAndWakeupHandlers(ServerBlockHandlerProcPtr blockHandler, 18 ServerWakeupHandlerProcP tr wakeupHandler, 19 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

处理屏幕旋转