ReactOS 图形系统分析(4):GDI 引擎 (eng)
1. 概述
GDI 引擎(Graphics Device Interface Engine) 位于 win32ss/gdi/eng/,是 ReactOS 图形子系统(win32k.sys)的核心渲染引擎 。它实现了 Windows GDI 的 DDI(Device Driver Interface) 层,向上服务内核 GDI(ntgdi/)的绘图请求,向下调度显示驱动的硬件加速回调,并为无硬件加速的情况提供完整的软件渲染回退。
┌─────────────────────────────────────────────┐
│ ntgdi/ (内核 GDI:对象管理、DC、系统调用) │
├─────────────────────────────────────────────┤
│ gdi/eng/ (GDI 引擎 ← 本分析对象) │
│ - 表面管理 / 裁剪 / 位块传输 / 画刷 │
│ - 设备对象 (PDEV/LDEV/MDEV) 管理 │
│ - DDI 分发:调用驱动 or 软件渲染 │
├──────────────┬──────────────┬───────────────┤
│ gdi/dib/ │ 显示驱动 DDI │ 字体驱动 │
│ (软件渲染) │ framebuf/vga │ bmfd/ftfd │
└──────────────┴──────────────┴───────────────┘
1.1 模块文件构成
| 文件 | 功能 |
|---|---|
| surface.c(file:///d:/reactos/win32ss/gdi/eng/surface.c) / surface.h(file:///d:/reactos/win32ss/gdi/eng/surface.h) | 表面管理:EngCreateSurface/EngModifySurface/EngLockSurface |
| bitblt.c(file:///d:/reactos/win32ss/gdi/eng/bitblt.c) | 位块传输核心:EngBitBlt、IntEngBitBlt、MaskBlt |
| clip.c(file:///d:/reactos/win32ss/gdi/eng/clip.c) | 裁剪:EngCreateClip、CLIPOBJ 枚举 |
| pdevobj.c(file:///d:/reactos/win32ss/gdi/eng/pdevobj.c) / pdevobj.h(file:///d:/reactos/win32ss/gdi/eng/pdevobj.h) | 物理设备对象管理 |
| ldevobj.c(file:///d:/reactos/win32ss/gdi/eng/ldevobj.c) / ldevobj.h(file:///d:/reactos/win32ss/gdi/eng/ldevobj.h) | 逻辑设备对象管理(驱动加载) |
| mdevobj.c(file:///d:/reactos/win32ss/gdi/eng/mdevobj.c) / mdevobj.h(file:///d:/reactos/win32ss/gdi/eng/mdevobj.h) | 映射设备对象(多显示器) |
| device.c(file:///d:/reactos/win32ss/gdi/eng/device.c) | 图形设备注册表、EngpRegisterGraphicsDevice |
| driverobj.c(file:///d:/reactos/win32ss/gdi/eng/driverobj.c) / driverobj.h(file:///d:/reactos/win32ss/gdi/eng/driverobj.h) | 驱动对象管理 |
| engbrush.c(file:///d:/reactos/win32ss/gdi/eng/engbrush.c) | 画刷对象:BRUSHOBJ 管理 |
| engwindow.c(file:///d:/reactos/win32ss/gdi/eng/engwindow.c) | 窗口对象(EWNDOBJ)管理 |
| lineto.c(file:///d:/reactos/win32ss/gdi/eng/lineto.c) | 线条绘制(IntEngLineTo) |
| string.c(file:///d:/reactos/win32ss/gdi/eng/string.c) | 字符串绘制(IntEngTextOut 相关) |
| paint.c(file:///d:/reactos/win32ss/gdi/eng/paint.c) | 区域填充 |
| pathobj.c(file:///d:/reactos/win32ss/gdi/eng/pathobj.c) | 路径对象 |
| xlateobj.c(file:///d:/reactos/win32ss/gdi/eng/xlateobj.c) / xlateobj.h(file:///d:/reactos/win32ss/gdi/eng/xlateobj.h) | 颜色转换对象 |
| semaphor.c(file:///d:/reactos/win32ss/gdi/eng/semaphor.c) | 信号量:EngAcquireSemaphore |
| mapping.c(file:///d:/reactos/win32ss/gdi/eng/mapping.c) / mapping.h(file:///d:/reactos/win32ss/gdi/eng/mapping.h) | 坐标映射 |
| math.c(file:///d:/reactos/win32ss/gdi/eng/math.c) / float.c(file:///d:/reactos/win32ss/gdi/eng/float.c) | 数学/浮点运算 |
| mem.c(file:///d:/reactos/win32ss/gdi/eng/mem.c) | 引擎内存分配 |
| mouse.c(file:///d:/reactos/win32ss/gdi/eng/mouse.c) / mouse.h(file:///d:/reactos/win32ss/gdi/eng/mouse.h) | 指针(光标)管理 |
| multidisp.c(file:///d:/reactos/win32ss/gdi/eng/multidisp.c) / pandisp.c(file:///d:/reactos/win32ss/gdi/eng/pandisp.c) | 多显示器/平移显示 |
| engmisc.c(file:///d:/reactos/win32ss/gdi/eng/engmisc.c) | 杂项 |
| alphablend.c(file:///d:/reactos/win32ss/gdi/eng/alphablend.c) | Alpha 混合 |
| gradient.c(file:///d:/reactos/win32ss/gdi/eng/gradient.c) | 渐变填充 |
| stretchblt.c(file:///d:/reactos/win32ss/gdi/eng/stretchblt.c) / transblt.c(file:///d:/reactos/win32ss/gdi/eng/transblt.c) | 拉伸/透明传输 |
| rlecomp.c(file:///d:/reactos/win32ss/gdi/eng/rlecomp.c) | RLE 压缩 |
| sort.c(file:///d:/reactos/win32ss/gdi/eng/sort.c) | 排序工具 |
| engevent.c(file:///d:/reactos/win32ss/gdi/eng/engevent.c) / engevent.h(file:///d:/reactos/win32ss/gdi/eng/engevent.h) | 事件对象 |
| stubs.c(file:///d:/reactos/win32ss/gdi/eng/stubs.c) / umpdstubs.c(file:///d:/reactos/win32ss/gdi/eng/umpdstubs.c) | 桩函数 |
| eng.h(file:///d:/reactos/win32ss/gdi/eng/eng.h) | 引擎内部 API 声明 |
| inteng.h(file:///d:/reactos/win32ss/gdi/eng/inteng.h) | IntEng* 内部接口 |
| engobjects.h(file:///d:/reactos/win32ss/gdi/eng/engobjects.h) | 内部对象(XCLIPOBJ/EWNDOBJ) |
2. 核心数据结构
2.1 SURFACE --- 引擎表面(surface.h(file:///d:/reactos/win32ss/gdi/eng/surface.h))
引擎管理的所有可绘制表面(屏幕、位图、DIB section)统一用 SURFACE 表示,其公开部分是 DDI 层使用的 SURFOBJ:
c
typedef struct _SURFACE
{
BASEOBJECT BaseObject; // GDI 对象头(句柄/锁/标志)
SURFOBJ SurfObj; // 公开的 SURFOBJ(DDI 层使用)
FLONG flags; // 表面标志(HOOK_* 位、类型位)
struct _PALETTE * const ppal; // 关联调色板
struct _EWNDOBJ *pWinObj; // 窗口对象(窗口表面)
union {
HANDLE hSecureUMPD; // UMPD 表面
HANDLE hMirrorParent; // 镜像表面
HANDLE hDDSurface; // DirectDraw 表面
};
SIZEL sizlDim; // 位图尺寸
HDC hdc; // 关联 DC
ULONG cRef; // 引用计数
HPALETTE hpalHint;
HANDLE hDIBSection; // DIB Section
HANDLE hSecure;
DWORD dwOffset;
DWORD biClrImportant;
ULONG biCompression;
} SURFACE, *PSURFACE;
SURFOBJ(DDI 公开部分)字段:
| 字段 | 含义 |
|---|---|
sizlBitmap |
表面尺寸(宽×高) |
pvBits / pvScan0 |
像素数据地址(帧缓冲或系统内存) |
lDelta |
行距(每行字节数) |
iBitmapFormat |
位图格式(BMF_1BPP ~ BMF_32BPP) |
iType |
类型(STYPE_BITMAP / STYPE_DEVICE) |
hpal |
调色板句柄 |
dhpdev / hdev |
关联设备 |
表面标志位(_SURFACEFLAGS)关键项:
HOOK_BITBLT // 目标表面挂钩了驱动 DrvBitBlt
HOOK_STRETCHBLT // 挂钩了 DrvStretchBlt
HOOK_TEXTOUT // 挂钩了 DrvTextOut
HOOK_LINETO // 挂钩了 DrvLineTo
...
UMDP_SURFACE // 用户模式驱动的表面
MIRROR_SURFACE // 镜像表面
DIRECTDRAW_SURFACE // DirectDraw 表面
PDEV_SURFACE // 设备表面(屏幕)
API_BITMAP // 应用创建的位图
DDB_SURFACE // 设备相关位图
2.2 XCLIPOBJ / CLIPOBJ --- 扩展裁剪对象(engobjects.h(file:///d:/reactos/win32ss/gdi/eng/engobjects.h))
CLIPOBJ 是 DDI 层公开的裁剪对象;引擎内部使用扩展的 XCLIPOBJ(= CLIPOBJ + RWNDOBJ + 私有字段):
c
typedef struct _XCLIPOBJ
{
CLIPOBJ; // 公开部分:rclBounds, iDComplexity, iMode 等
RWNDOBJ; // 窗口对象:pvConsumer, rclClient, psoOwner
struct _REGION *pClipRgn; // 裁剪区域(Rao 区域或 Vis 区域)
RECTL rclClipRgn; // 裁剪矩形
RECTL* Rects; // 枚举用矩形缓冲区
DWORD cScan; // 扫描段数
ULONG EnumPos; // 枚举位置
ULONG iDirection; // 枚举方向(CD_ANY/CD_LEFTDOWN 等)
ULONG iType; // 裁剪类型
LONG lUpDown; // 从上到下标记
BOOL bAll; // 是否全矩形
DWORD RectCount;
PVOID pDDA;
} XCLIPOBJ, *PXCLIPOBJ;
裁剪复杂度(iDComplexity,决定渲染策略):
DC_TRIVIAL--- 无裁剪(全矩形),直接绘制DC_RECT--- 单一矩形裁剪DC_COMPLEX--- 复杂区域,需要矩形枚举逐块绘制
EngCreateClip 分配 {XCLIPOBJ co; REGION ro;} 组合结构,pco->co.pClipRgn = &pco->ro。
窗口表面扩展: EWNDOBJ(= XCLIPOBJ + HWND + ChangeProc + PixelFormat)用于窗口表面,使显示驱动能跟踪窗口变化。
2.3 设备对象体系
引擎用四层对象管理显示设备(详见 ReactOS图形系统架构分析.md 第 3.3 节):
LDEVOBJ (逻辑设备:驱动加载 + DDI 函数表)
↓ 引用
PDEVOBJ (物理设备:DrvEnablePDEV 初始化硬件)
↓ 拥有
SURFACE (显示表面:DrvEnableSurface 创建)
↓ 聚合
MDEVOBJ (映射设备:管理多个 PDEV,多显示器)
PDEVOBJ 关键字段: ppdevNext(链表)、cPdevRefs(引用计数)、hsemDevLock(设备锁)、ahsurf[HS_DDI_MAX](引擎表面句柄数组)、flFlags(PDEV_DISPLAY/PDEV_PRINTER 等)。
LDEVOBJ 核心:
c
typedef struct _LDEVOBJ
{
LIST_ENTRY leLink;
SYSTEM_GDI_DRIVER_INFORMATION *pGdiDriverInfo;
LDEVTYPE ldevtype; // LDEV_DEVICE_DISPLAY / PRINTER / META / MIRROR / FONT
ULONG cRefs;
ULONG ulDriverVersion;
union {
PVOID apfn[INDEX_LAST]; // DDI 函数指针数组
DRIVER_FUNCTIONS pfn; // 具名 DDI 函数表
};
} LDEVOBJ, *PLDEVOBJ;
LDEV 的 DDI 函数表包含显示驱动可实现的全部回调(INDEX_DrvEnablePDEV ~ INDEX_DrvTextOut 等),引擎通过 GDIDEVFUNCS(surf) 宏从表面取得设备函数表。
3. 核心功能模块
3.1 位块传输 --- EngBitBlt / IntEngBitBlt(bitblt.c(file:///d:/reactos/win32ss/gdi/eng/bitblt.c))
BitBlt 是引擎最核心的操作。存在双层实现:
第一层:IntEngBitBlt(设备挂钩决策)
#mermaid-svg-Q3fMdO3m3gmmJMBF{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Q3fMdO3m3gmmJMBF .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Q3fMdO3m3gmmJMBF .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Q3fMdO3m3gmmJMBF .error-icon{fill:#552222;}#mermaid-svg-Q3fMdO3m3gmmJMBF .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Q3fMdO3m3gmmJMBF .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Q3fMdO3m3gmmJMBF .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Q3fMdO3m3gmmJMBF .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Q3fMdO3m3gmmJMBF .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Q3fMdO3m3gmmJMBF .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Q3fMdO3m3gmmJMBF .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Q3fMdO3m3gmmJMBF .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Q3fMdO3m3gmmJMBF .marker.cross{stroke:#333333;}#mermaid-svg-Q3fMdO3m3gmmJMBF svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Q3fMdO3m3gmmJMBF p{margin:0;}#mermaid-svg-Q3fMdO3m3gmmJMBF .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Q3fMdO3m3gmmJMBF .cluster-label text{fill:#333;}#mermaid-svg-Q3fMdO3m3gmmJMBF .cluster-label span{color:#333;}#mermaid-svg-Q3fMdO3m3gmmJMBF .cluster-label span p{background-color:transparent;}#mermaid-svg-Q3fMdO3m3gmmJMBF .label text,#mermaid-svg-Q3fMdO3m3gmmJMBF span{fill:#333;color:#333;}#mermaid-svg-Q3fMdO3m3gmmJMBF .node rect,#mermaid-svg-Q3fMdO3m3gmmJMBF .node circle,#mermaid-svg-Q3fMdO3m3gmmJMBF .node ellipse,#mermaid-svg-Q3fMdO3m3gmmJMBF .node polygon,#mermaid-svg-Q3fMdO3m3gmmJMBF .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Q3fMdO3m3gmmJMBF .rough-node .label text,#mermaid-svg-Q3fMdO3m3gmmJMBF .node .label text,#mermaid-svg-Q3fMdO3m3gmmJMBF .image-shape .label,#mermaid-svg-Q3fMdO3m3gmmJMBF .icon-shape .label{text-anchor:middle;}#mermaid-svg-Q3fMdO3m3gmmJMBF .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Q3fMdO3m3gmmJMBF .rough-node .label,#mermaid-svg-Q3fMdO3m3gmmJMBF .node .label,#mermaid-svg-Q3fMdO3m3gmmJMBF .image-shape .label,#mermaid-svg-Q3fMdO3m3gmmJMBF .icon-shape .label{text-align:center;}#mermaid-svg-Q3fMdO3m3gmmJMBF .node.clickable{cursor:pointer;}#mermaid-svg-Q3fMdO3m3gmmJMBF .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Q3fMdO3m3gmmJMBF .arrowheadPath{fill:#333333;}#mermaid-svg-Q3fMdO3m3gmmJMBF .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Q3fMdO3m3gmmJMBF .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Q3fMdO3m3gmmJMBF .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Q3fMdO3m3gmmJMBF .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Q3fMdO3m3gmmJMBF .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Q3fMdO3m3gmmJMBF .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Q3fMdO3m3gmmJMBF .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Q3fMdO3m3gmmJMBF .cluster text{fill:#333;}#mermaid-svg-Q3fMdO3m3gmmJMBF .cluster span{color:#333;}#mermaid-svg-Q3fMdO3m3gmmJMBF div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Q3fMdO3m3gmmJMBF .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Q3fMdO3m3gmmJMBF rect.text{fill:none;stroke-width:0;}#mermaid-svg-Q3fMdO3m3gmmJMBF .icon-shape,#mermaid-svg-Q3fMdO3m3gmmJMBF .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Q3fMdO3m3gmmJMBF .icon-shape p,#mermaid-svg-Q3fMdO3m3gmmJMBF .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Q3fMdO3m3gmmJMBF .icon-shape .label rect,#mermaid-svg-Q3fMdO3m3gmmJMBF .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Q3fMdO3m3gmmJMBF .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Q3fMdO3m3gmmJMBF .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Q3fMdO3m3gmmJMBF :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
是
否
是
否
是
否
IntEngBitBlt
(内部入口,被 ntgdi 调用)
裁剪目标矩形
到目标表面尺寸
与 pco->rclBounds 求交
pco 是 DC_RECT?
pco = NULL (简化)
保留 pco
ROP 使用源?
计算源矩形并裁剪
到源表面尺寸
修正目标矩形
psoSrc = NULL
目标表面
HOOK_BITBLT?
pfnBitBlt = GDIDEVFUNCS(目标).BitBlt
(调用显示驱动 DrvBitBlt)
源表面
HOOK_BITBLT?
pfnBitBlt = GDIDEVFUNCS(源).BitBlt
pfnBitBlt = EngBitBlt
(引擎软件实现)
按翻转修正矩形
(左→右/上→下)
调用 pfnBitBlt 执行
关键代码:
c
/* 决定调用哪个 BitBlt 实现 */
if (psurfTrg->flags & HOOK_BITBLT)
{
pfnBitBlt = GDIDEVFUNCS(psoTrg).BitBlt; // 目标表面挂钩了驱动 → 调驱动
}
else if (psoSrc && psurfSrc->flags & HOOK_BITBLT)
{
pfnBitBlt = GDIDEVFUNCS(psoSrc).BitBlt; // 源表面挂钩了驱动 → 调驱动
}
else
{
pfnBitBlt = EngBitBlt; // 否则软件渲染
}
第二层:EngBitBlt(软件渲染,含裁剪分析)
#mermaid-svg-qT0R2VvxduZNRxSt{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-qT0R2VvxduZNRxSt .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-qT0R2VvxduZNRxSt .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-qT0R2VvxduZNRxSt .error-icon{fill:#552222;}#mermaid-svg-qT0R2VvxduZNRxSt .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-qT0R2VvxduZNRxSt .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-qT0R2VvxduZNRxSt .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-qT0R2VvxduZNRxSt .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-qT0R2VvxduZNRxSt .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-qT0R2VvxduZNRxSt .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-qT0R2VvxduZNRxSt .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-qT0R2VvxduZNRxSt .marker{fill:#333333;stroke:#333333;}#mermaid-svg-qT0R2VvxduZNRxSt .marker.cross{stroke:#333333;}#mermaid-svg-qT0R2VvxduZNRxSt svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-qT0R2VvxduZNRxSt p{margin:0;}#mermaid-svg-qT0R2VvxduZNRxSt .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-qT0R2VvxduZNRxSt .cluster-label text{fill:#333;}#mermaid-svg-qT0R2VvxduZNRxSt .cluster-label span{color:#333;}#mermaid-svg-qT0R2VvxduZNRxSt .cluster-label span p{background-color:transparent;}#mermaid-svg-qT0R2VvxduZNRxSt .label text,#mermaid-svg-qT0R2VvxduZNRxSt span{fill:#333;color:#333;}#mermaid-svg-qT0R2VvxduZNRxSt .node rect,#mermaid-svg-qT0R2VvxduZNRxSt .node circle,#mermaid-svg-qT0R2VvxduZNRxSt .node ellipse,#mermaid-svg-qT0R2VvxduZNRxSt .node polygon,#mermaid-svg-qT0R2VvxduZNRxSt .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-qT0R2VvxduZNRxSt .rough-node .label text,#mermaid-svg-qT0R2VvxduZNRxSt .node .label text,#mermaid-svg-qT0R2VvxduZNRxSt .image-shape .label,#mermaid-svg-qT0R2VvxduZNRxSt .icon-shape .label{text-anchor:middle;}#mermaid-svg-qT0R2VvxduZNRxSt .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-qT0R2VvxduZNRxSt .rough-node .label,#mermaid-svg-qT0R2VvxduZNRxSt .node .label,#mermaid-svg-qT0R2VvxduZNRxSt .image-shape .label,#mermaid-svg-qT0R2VvxduZNRxSt .icon-shape .label{text-align:center;}#mermaid-svg-qT0R2VvxduZNRxSt .node.clickable{cursor:pointer;}#mermaid-svg-qT0R2VvxduZNRxSt .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-qT0R2VvxduZNRxSt .arrowheadPath{fill:#333333;}#mermaid-svg-qT0R2VvxduZNRxSt .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-qT0R2VvxduZNRxSt .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-qT0R2VvxduZNRxSt .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qT0R2VvxduZNRxSt .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-qT0R2VvxduZNRxSt .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qT0R2VvxduZNRxSt .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-qT0R2VvxduZNRxSt .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-qT0R2VvxduZNRxSt .cluster text{fill:#333;}#mermaid-svg-qT0R2VvxduZNRxSt .cluster span{color:#333;}#mermaid-svg-qT0R2VvxduZNRxSt div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-qT0R2VvxduZNRxSt .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-qT0R2VvxduZNRxSt rect.text{fill:none;stroke-width:0;}#mermaid-svg-qT0R2VvxduZNRxSt .icon-shape,#mermaid-svg-qT0R2VvxduZNRxSt .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qT0R2VvxduZNRxSt .icon-shape p,#mermaid-svg-qT0R2VvxduZNRxSt .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-qT0R2VvxduZNRxSt .icon-shape .label rect,#mermaid-svg-qT0R2VvxduZNRxSt .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qT0R2VvxduZNRxSt .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-qT0R2VvxduZNRxSt .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-qT0R2VvxduZNRxSt :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
是
否
DC_TRIVIAL
DC_RECT
DC_COMPLEX
EngBitBlt
(软件实现)
分析 ROP4 使用情况
UsesSource/UsesMask
翻转方向 bLeftToRight/bTopToBottom
ROP4 == NOOP?
直接返回 (空操作)
规范化目标矩形
RECTL_vMakeWellOrdered
使用源?
源点/源矩形裁剪
防越界
无源
与裁剪边界求交
限制在 pco->rclBounds
裁剪类型?
恢复翻转方向
直接调用 BltRectFunc 一次
与裁剪矩形求交
调用一次 BltRectFunc
确定绘制方向
CLIPOBJ_cEnumStart 初始化枚举
CLIPOBJ_bEnum 循环枚举矩形
逐矩形求交并调用 BltRectFunc
返回结果
BltRectFunc 选择(引擎内部分发到 DIB 引擎):
c
if (UsesMask)
{
BltRectFunc = BltMask; // 带掩码传输
}
else if ((rop4 & 0xFF) == R3_OPINDEX_PATCOPY && 纯色画刷)
{
BltRectFunc = BltPatCopy; // 纯色填充(DIB_ColorFill)
}
else
{
BltRectFunc = CallDibBitBlt; // 通用 → DIB 函数表
}
CallDibBitBlt 构造 BLTINFO 并调用 DibFunctionsForBitmapFormat[格式].DIB_BitBlt(SRCCOPY 走 DIB_BitBltSrcCopy 快路径),最终由 DIB 引擎完成像素级操作(见《ReactOS图形系统架构分析.md》第 6 章)。
ROP4 宏(inteng.h(file:///d:/reactos/win32ss/gdi/eng/inteng.h)):
c
#define ROP4_USES_DEST(Rop4) ((((Rop4) & 0xAAAA) >> 1) != ((Rop4) & 0x5555))
#define ROP4_USES_SOURCE(Rop4) ((((Rop4) & 0xCCCC) >> 2) != ((Rop4) & 0x3333))
#define ROP4_USES_PATTERN(Rop4) ((((Rop4) & 0xF0F0) >> 4) != ((Rop4) & 0x0F0F))
#define ROP4_USES_MASK(Rop4) ((((Rop4) & 0xFF00) >> 8) != ((Rop4) & 0x00ff))
ROP4 高字节为背景 ROP、低字节为前景 ROP;引擎据此判断操作依赖哪些输入(源/图案/掩码),决定是否剪裁对应表面。
3.2 裁剪管理 --- clip.c
c
HCLIP APIENTRY EngCreateClip(VOID) // 创建 XCLIPOBJ + REGION 组合对象
CLIPOBJ_cEnumStart(pco, ..., CT_RECTANGLES, Direction, 0) // 初始化矩形枚举
CLIPOBJ_bEnum(pco, sizeof(RECT_ENUM), (PVOID)&RectEnum) // 枚举下一批矩形(最多 32 个)
裁剪区域枚举把复杂区域拆成矩形列表,RECT_ENUM 单次最多返回 ENUM_RECT_LIMIT(32) 个矩形,CLIPOBJ_bEnum 返回 TRUE 表示还有更多。
3.3 表面管理 --- surface.c
| 函数 | 功能 |
|---|---|
EngCreateSurface |
创建引擎表面(分配 SURFACE) |
EngCreateDeviceSurface |
为设备创建表面(显示驱动用) |
EngModifySurface |
修改表面(重新指定像素/格式) |
EngLockSurface / EngUnlockSurface |
锁定/解锁表面(返回 SURFOBJ) |
EngDeleteSurface |
删除表面 |
EngAssociateSurface |
将表面关联到设备(framebuf 用它绑定屏幕表面) |
EngCopyBits |
表面间位复制 |
EngGetCurrentCodePage |
代码页查询 |
3.4 设备对象管理
PDEVOBJ(pdevobj.c(file:///d:/reactos/win32ss/gdi/eng/pdevobj.c))核心函数:
| 函数 | 功能 |
|---|---|
PDEVOBJ_AllocPDEV |
分配 PDEV |
PDEVOBJ_vDeletePDEV |
删除 PDEV |
PDEVOBJ_bEnablePDEV |
调用 DrvEnablePDEV 启用设备 |
PDEVOBJ_vCompletePDEV |
完成设备初始化 |
PDEVOBJ_bEnableDirectDraw |
启用 DirectDraw |
PDEVOBJ_bDynamicModeChange |
动态模式切换 |
PDEVOBJ_bSwitchMode |
切换显示模式 |
PDEVOBJ_lChangeDisplaySettings |
修改显示设置(ChangeDisplaySettings 内核实现) |
PDEVOBJ_vRefreshModeList |
刷新模式列表 |
LDEVOBJ(ldevobj.c(file:///d:/reactos/win32ss/gdi/eng/ldevobj.c))核心函数:
| 函数 | 功能 |
|---|---|
LDEVOBJ_pLoadDriver |
加载指定名称的显示驱动 |
LDEVOBJ_pLoadInternal |
加载内部驱动(DIB 引擎等) |
LDEVOBJ_bBuildDevmodeList |
构建 DEVMODE 列表 |
LDEVOBJ_bProbeAndCaptureDevmode |
选择最佳 DEVMODE |
设备注册(device.c(file:///d:/reactos/win32ss/gdi/eng/device.c)):
c
PGRAPHICS_DEVICE EngpRegisterGraphicsDevice(
PUNICODE_STRING pusDeviceName, // 设备名
PUNICODE_STRING pusDisplayDrivers, // InstalledDisplayDrivers(多驱动)
PUNICODE_STRING pusDescription) // 设备描述
维护全局图形设备链表(gpGraphicsDeviceFirst/Last):
gpPrimaryGraphicsDevice--- 主显示设备gpVgaGraphicsDevice--- VGA 兼容设备(win32k 查找时优先)- 每个设备带
hLdev(逻辑设备)、cPdev等
3.5 引擎信号量 --- semaphor.c
c
EngAcquireSemaphore(hsem) // 排他获取
EngAcquireSemaphoreShared(hsem) // 共享获取(读锁)
EngReleaseSemaphore(hsem) // 释放
EngDeleteSemaphore(hsem) // 删除
EngCreateSemaphore() // 创建
引擎用信号量保护设备列表、表面引用计数等全局状态。
3.6 画刷对象 --- engbrush.c
EBRUSHOBJ(引擎画刷对象)封装画刷,核心操作:
BRUSHOBJ_psoPattern--- 获取图案表面(图案画刷)BRUSHOBJ_pvGetRbrush--- 获取驱动画刷- 纯色画刷用
iSolidColor(0xFFFFFFFF 表示非纯色,需图案) - 虚线/几何画刷的构建
引擎在 BitBlt 中使用画刷判断:pbo->iSolidColor == 0xFFFFFFFF 时从 BRUSHOBJ_psoPattern 获取图案表面作为 PatternSurface 传给 DIB 引擎。
3.7 其他核心功能
| 模块 | 函数 | 功能 |
|---|---|---|
| lineto.c | IntEngLineTo |
直线绘制(Bresenham 或驱动 DrvLineTo) |
| string.c | IntEngTextOut |
文本输出 |
| paint.c | IntEngFillPath 等 |
路径填充 |
| alphablend.c | EngAlphaBlend |
Alpha 混合 |
| gradient.c | EngGradientFill |
渐变填充 |
| stretchblt.c | EngStretchBlt |
拉伸位块传输 |
| transblt.c | EngTransparentBlt |
透明位块传输 |
| xlateobj.c | EngCreateXlate 等 |
颜色转换对象 |
| mouse.c | 指针管理 | 光标表面管理 |
| engwindow.c | EWNDOBJ | 窗口对象跟踪 |
| engevent.c | EngCreateEvent | 事件对象 |
| mem.c | EngAllocMem | 引擎内存分配 |
| float.c/math.c | FLOATOBJ | 浮点坐标计算 |
4. 渲染管线(引擎视角)
#mermaid-svg-VAscw6FVoZsg9nxg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-VAscw6FVoZsg9nxg .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-VAscw6FVoZsg9nxg .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-VAscw6FVoZsg9nxg .error-icon{fill:#552222;}#mermaid-svg-VAscw6FVoZsg9nxg .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-VAscw6FVoZsg9nxg .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-VAscw6FVoZsg9nxg .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-VAscw6FVoZsg9nxg .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-VAscw6FVoZsg9nxg .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-VAscw6FVoZsg9nxg .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-VAscw6FVoZsg9nxg .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-VAscw6FVoZsg9nxg .marker{fill:#333333;stroke:#333333;}#mermaid-svg-VAscw6FVoZsg9nxg .marker.cross{stroke:#333333;}#mermaid-svg-VAscw6FVoZsg9nxg svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-VAscw6FVoZsg9nxg p{margin:0;}#mermaid-svg-VAscw6FVoZsg9nxg .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-VAscw6FVoZsg9nxg .cluster-label text{fill:#333;}#mermaid-svg-VAscw6FVoZsg9nxg .cluster-label span{color:#333;}#mermaid-svg-VAscw6FVoZsg9nxg .cluster-label span p{background-color:transparent;}#mermaid-svg-VAscw6FVoZsg9nxg .label text,#mermaid-svg-VAscw6FVoZsg9nxg span{fill:#333;color:#333;}#mermaid-svg-VAscw6FVoZsg9nxg .node rect,#mermaid-svg-VAscw6FVoZsg9nxg .node circle,#mermaid-svg-VAscw6FVoZsg9nxg .node ellipse,#mermaid-svg-VAscw6FVoZsg9nxg .node polygon,#mermaid-svg-VAscw6FVoZsg9nxg .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-VAscw6FVoZsg9nxg .rough-node .label text,#mermaid-svg-VAscw6FVoZsg9nxg .node .label text,#mermaid-svg-VAscw6FVoZsg9nxg .image-shape .label,#mermaid-svg-VAscw6FVoZsg9nxg .icon-shape .label{text-anchor:middle;}#mermaid-svg-VAscw6FVoZsg9nxg .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-VAscw6FVoZsg9nxg .rough-node .label,#mermaid-svg-VAscw6FVoZsg9nxg .node .label,#mermaid-svg-VAscw6FVoZsg9nxg .image-shape .label,#mermaid-svg-VAscw6FVoZsg9nxg .icon-shape .label{text-align:center;}#mermaid-svg-VAscw6FVoZsg9nxg .node.clickable{cursor:pointer;}#mermaid-svg-VAscw6FVoZsg9nxg .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-VAscw6FVoZsg9nxg .arrowheadPath{fill:#333333;}#mermaid-svg-VAscw6FVoZsg9nxg .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-VAscw6FVoZsg9nxg .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-VAscw6FVoZsg9nxg .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VAscw6FVoZsg9nxg .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-VAscw6FVoZsg9nxg .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VAscw6FVoZsg9nxg .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-VAscw6FVoZsg9nxg .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-VAscw6FVoZsg9nxg .cluster text{fill:#333;}#mermaid-svg-VAscw6FVoZsg9nxg .cluster span{color:#333;}#mermaid-svg-VAscw6FVoZsg9nxg div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-VAscw6FVoZsg9nxg .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-VAscw6FVoZsg9nxg rect.text{fill:none;stroke-width:0;}#mermaid-svg-VAscw6FVoZsg9nxg .icon-shape,#mermaid-svg-VAscw6FVoZsg9nxg .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VAscw6FVoZsg9nxg .icon-shape p,#mermaid-svg-VAscw6FVoZsg9nxg .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-VAscw6FVoZsg9nxg .icon-shape .label rect,#mermaid-svg-VAscw6FVoZsg9nxg .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VAscw6FVoZsg9nxg .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-VAscw6FVoZsg9nxg .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-VAscw6FVoZsg9nxg :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 显示驱动/硬件
gdi/dib/ (软件渲染)
gdi/eng/ (引擎)
ntgdi/ (内核 GDI)
是
否
NtGdiBitBlt / NtGdiTextOut / NtGdiLineTo
DC 处理:裁剪区域合成
prgnVis/prgnRao/prgnAPI
XCLIPOBJ 构造
EngCreateClip + 区域求交
IntEngBitBlt / IntEngLineTo / IntEngTextOut
目标表面挂钩了驱动?
(HOOK_* 标志)
调用 DDI:DrvBitBlt/DrvLineTo/DrvTextOut
(硬件加速)
EngBitBlt 软件路径
裁剪分析 (TRIVIAL/RECT/COMPLEX)
DIB 函数表分发
DibFunctionsForBitmapFormat
DIB_32BPP_BitBlt / PutPixel 等
按位深实现
framebuf.dll 等
(DrvBitBlt 回调)
帧缓冲/显存
渲染决策核心: 引擎通过表面的 HOOK_* 标志判断驱动是否实现了某 DDI。例如目标表面(屏幕)如果被 framebuf 挂钩了 HOOK_BITBLT,则调用 GDIDEVFUNCS(psoTrg).BitBlt;但 framebuf 不实现 DrvBitBlt(见《ReactOS 图形系统分析_3.md》),因此实际仍回退到 EngBitBlt 软件渲染。
5. 与显示驱动的 DDI 交互
5.1 DDI 函数索引
引擎通过 INDEX_* 常量索引驱动的 DDI 函数表(GDIDEVFUNCS 宏从表面取 hdev → LDEVOBJ → 函数表):
c
#define GDIDEVFUNCS(pso) \
(LDEVOBJ_pLDevObjForSurface(pso)->pfn)
常用索引:INDEX_DrvEnablePDEV、INDEX_DrvEnableSurface、INDEX_DrvBitBlt、INDEX_DrvTextOut、INDEX_DrvLineTo、INDEX_DrvStretchBlt、INDEX_DrvSetPalette、INDEX_DrvGetModes 等(共 INDEX_LAST 个)。
5.2 钩子标志与 DDI 调度
| HOOK_* 标志 | 对应 DDI | 引擎回退实现 |
|---|---|---|
| HOOK_BITBLT | DrvBitBlt | EngBitBlt → DIB_BitBlt |
| HOOK_STRETCHBLT | DrvStretchBlt | EngStretchBlt |
| HOOK_TEXTOUT | DrvTextOut | IntEngTextOut |
| HOOK_LINETO | DrvLineTo | IntEngLineTo |
| HOOK_FILLPATH | DrvFillPath | EngFillPath |
| HOOK_STROKEPATH | DrvStrokePath | EngStrokePath |
回退原则: 驱动未挂钩的操作一律由引擎软件实现兜底------这是显示驱动可以"极简"(如 framebuf 只实现 12 个 DDI)的根本原因。
6. 构建配置
cmake
# win32ss/CMakeLists.txt 中 win32k.sys 的 eng/ 部分
gdi/eng/bitblt.c
gdi/eng/bitblt_new.c # 新版(USE_DIBLIB 时)
gdi/eng/clip.c
gdi/eng/device.c
gdi/eng/driverobj.c
gdi/eng/engbrush.c
gdi/eng/engevent.c
gdi/eng/engmisc.c
gdi/eng/engwindow.c
gdi/eng/error.c
gdi/eng/float.c
gdi/eng/gradient.c
gdi/eng/ldevobj.c
gdi/eng/lineto.c
gdi/eng/mapping.c
gdi/eng/math.c
gdi/eng/mdevobj.c
gdi/eng/mem.c
gdi/eng/mouse.c
gdi/eng/multidisp.c
gdi/eng/paint.c
gdi/eng/pandisp.c
gdi/eng/pathobj.c
gdi/eng/pdevobj.c
gdi/eng/perfcnt.c
gdi/eng/rlecomp.c
gdi/eng/semaphor.c
gdi/eng/sort.c
gdi/eng/stretchblt.c
gdi/eng/string.c
gdi/eng/surface.c
gdi/eng/transblt.c
gdi/eng/xlateobj.c
gdi/eng/stubs.c
gdi/eng/umpdstubs.c
gdi/eng/copybits.c
gdi/eng/alphablend.c
引擎代码全部编译进 win32k.sys(与 ntgdi、ntuser、dib 同一模块),非独立 DLL。
7. 设计特点总结
- 单一内核模块:引擎、内核 GDI、DIB 渲染全部编译进 win32k.sys,无跨模块边界开销。
- HOOK 标志驱动的 DDI 调度 :通过表面
HOOK_*标志判断是否调用驱动实现,未挂钩一律软件回退------这是显示驱动极简化(framebuf 仅 12 个 DDI)的架构基础。 - 双层 BitBlt :
IntEngBitBlt(设备决策+剪裁)→EngBitBlt(软件路径+裁剪枚举)→DIB_*(像素实现),层次清晰。 - 裁剪复杂度分级:DC_TRIVIAL/DC_RECT/DC_COMPLEX 三种复杂度对应"直接画/单次求交/矩形枚举"三种策略,兼顾简单与复杂场景性能。
- ROP4 输入分析:通过 ROP4 位运算判断操作依赖源/图案/掩码,提前剪裁或跳过不需要的表面。
- 四层设备对象:LDEV(驱动)→ PDEV(物理设备)→ SURFACE(表面)→ MDEV(多显示器),职责分离。
- 面向 DDI 的公开结构:SURFOBJ/CLIPOBJ/BRUSHOBJ/XLATEOBJ 等对象以 DDI 约定形式暴露,保证第三方显示驱动二进制兼容。
8. 源码索引
| 文件 | 关键内容 |
|---|---|
| eng.h(file:///d:/reactos/win32ss/gdi/eng/eng.h) | 引擎内部 API 声明、MIX_TO_ROP4 |
| inteng.h(file:///d:/reactos/win32ss/gdi/eng/inteng.h) | IntEng* 接口、ROP4 宏、SPAN 结构 |
| engobjects.h(file:///d:/reactos/win32ss/gdi/eng/engobjects.h) | XCLIPOBJ、EWNDOBJ、RWNDOBJ |
| surface.h(file:///d:/reactos/win32ss/gdi/eng/surface.h) / surface.c | SURFACE 结构、表面管理 |
| bitblt.c(file:///d:/reactos/win32ss/gdi/eng/bitblt.c) | EngBitBlt、IntEngBitBlt、BltMask、CallDibBitBlt |
| clip.c(file:///d:/reactos/win32ss/gdi/eng/clip.c) | EngCreateClip、CLIPOBJ_bEnum |
| pdevobj.h(file:///d:/reactos/win32ss/gdi/eng/pdevobj.h) / pdevobj.c | PDEVOBJ、模式切换 |
| ldevobj.h(file:///d:/reactos/win32ss/gdi/eng/ldevobj.h) / ldevobj.c | LDEVOBJ、驱动加载 |
| mdevobj.h(file:///d:/reactos/win32ss/gdi/eng/mdevobj.h) / mdevobj.c | MDEVOBJ 多显示器 |
| device.c(file:///d:/reactos/win32ss/gdi/eng/device.c) | GRAPHICS_DEVICE、EngpRegisterGraphicsDevice |
| engbrush.c(file:///d:/reactos/win32ss/gdi/eng/engbrush.c) | EBRUSHOBJ、BRUSHOBJ_psoPattern |
| lineto.c(file:///d:/reactos/win32ss/gdi/eng/lineto.c) | IntEngLineTo |
| string.c(file:///d:/reactos/win32ss/gdi/eng/string.c) | 文本输出 |
| xlateobj.h(file:///d:/reactos/win32ss/gdi/eng/xlateobj.h) / xlateobj.c | XLATEOBJ 颜色转换 |
| semaphor.c(file:///d:/reactos/win32ss/gdi/eng/semaphor.c) | 引擎信号量 |
关联模块:
- 上层调用者:ntgdi/(file:///d:/reactos/win32ss/gdi/ntgdi/bitblt.c)(内核 GDI 系统调用层)
- 软件渲染后端:gdi/dib/(file:///d:/reactos/win32ss/gdi/dib/dib.c) 与 gdi/diblib/(file:///d:/reactos/win32ss/gdi/diblib/DibLib.c)(DIB 函数表)
- 消费引擎服务的显示驱动:displays/framebuf/(file:///d:/reactos/win32ss/drivers/displays/framebuf/enable.c)(EngCreateBitmap 等)
- 设备注册来源:ntuser/display.c(file:///d:/reactos/win32ss/user/ntuser/display.c)(EngpRegisterGraphicsDevice)
本文档基于 ReactOS 源代码
win32ss/gdi/eng/分析(2026 年 8 月)