Chapter 121 · XUI 框架架构

渲染代理 xui_proxy_t

XUI 通过 proxy 抽象层与底层渲染引擎解耦,实现字体光栅化、Surface 创建、路径绘制等能力的可插拔。

121

概念

XUI 是纯逻辑 UI 框架,不直接调用任何 GPU API。 所有渲染操作通过 xui_proxy_t 回调结构体委托给宿主引擎:
• Surface 管理:创建/销毁/更新纹理表面
• 字体光栅化:加载字体、测量文本、渲染字形
• 路径绘制:填充/描边矢量路径
• 能力声明:xui_proxy_caps_t 告知 XUI 宿主支持的特性
XGE 引擎内置了完整的 proxy 实现,也可自定义。

API 速查

函数/结构说明
xui_proxy_t代理回调结构体(函数指针集合)
xui_proxy_caps_t能力声明(iCaps 位标志)
int xuiSetProxy(xui_context pContext, const xui_proxy_t* pProxy)设置渲染代理
int xuiGetProxy(xui_context pContext, xui_proxy_t* pProxy)获取当前代理
int xuiGetProxyCaps(xui_context pContext, xui_proxy_caps_t* pCaps)查询代理能力

编译本章示例

gcc -O2 -I. -o ch121.exe ch121_main.c src\xui_*.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch121.exe

示例:设置 XGE 内置代理

// XGE 提供开箱即用的 proxy 实现
extern const xui_proxy_t tXgeProxy;

// 创建 XUI 上下文后设置代理
xui_context pCtx;
xuiCreate(&pCtx);
xui_proxy_t tXgeProxy = xuiProxyXge();
xuiSetProxy(pCtx, &tXgeProxy);

// 查询代理能力
xui_proxy_caps_t caps;
xuiGetProxyCaps(pCtx, &caps);
printf("Surface format: %d\n",
    caps.iSurfaceFormat);
printf("Internal alpha: %d\n",
    caps.iInternalAlpha);

// 自定义 proxy(如纯软件渲染)
xui_proxy_t myProxy = { 0 };
myProxy.iVersion = XUI_PROXY_VERSION;
myProxy.pfnSurfaceCreate = mySurfaceCreate;
myProxy.pfnSurfaceDestroy = mySurfaceDestroy;
myProxy.pfnFontLoad = myFontLoad;
myProxy.pfnFontRasterize = myFontRasterize;
// ... 填充所有回调
xuiSetProxy(pCtx, &myProxy);

完整代码

将以下代码保存为 ch121_main.c,编译后运行即可看到代理能力查询输出:

#include "xge.h"
#include "xui.h"
#include <stdio.h>

static xui_context g_pCtx;

static int onFrame(void* pUser) {
    (void)pUser;
    xgeClear(0x081114FF);
    xuiUpdate(g_pCtx, xgeGetDelta());
    xuiLayout(g_pCtx);
    xuiRender(g_pCtx, NULL, NULL, 0);
    return XGE_OK;
}

int main(void) {
    xge_desc_t d = {0};
    d.iWidth  = 800;
    d.iHeight = 600;
    d.sTitle  = "ch121 - XUI Proxy";
    d.iFlags  = XGE_INIT_VSYNC;
    xgeInit(&d);

    // 创建 XUI 上下文并设置 XGE 内置代理
    xuiCreate(&g_pCtx);
    extern const xui_proxy_t tXgeProxy;
    xui_proxy_t tXgeProxy = xuiProxyXge();
xuiSetProxy(g_pCtx, &tXgeProxy);
    xuiSetViewportSize(g_pCtx, 800, 600);

    // 查询代理能力
    xui_proxy_caps_t caps;
    xuiGetProxyCaps(g_pCtx, &caps);
    printf("Surface format: %d\n", caps.iSurfaceFormat);
    printf("Internal alpha: %d\n", caps.iInternalAlpha);

    xgeRun(onFrame, NULL);

    xuiDestroy(g_pCtx);
    xgeUnit();
    return 0;
}

代码讲解

  • xuiCreate:创建 XUI 上下文,所有控件和状态都挂在此上下文上。
  • xuiSetProxy:将 XGE 内置的 tXgeProxy 绑定到上下文,使 XUI 能调用 XGE 渲染能力。
  • xuiSetViewportSize:告知 XUI 当前视口尺寸,用于布局计算。
  • xuiGetProxyCaps:查询代理支持的特性(Surface 格式、Alpha 混合等)。
  • 帧循环:xuiUpdate → xuiLayout → xuiRender 三步完成一帧 UI 更新。

要点与陷阱

  • 版本匹配:proxy.iVersion 必须为 XUI_PROXY_VERSION(当前 4)。
  • 解耦设计:XUI 不依赖 XGE,可对接任何渲染后端。
  • Caps 位:声明支持的能力(如 GPU 加速、YUV 纹理)。
  • 线程:proxy 回调在 xuiUpdate/xuiRender 时同步调用。

进阶练习

  1. 实现最小 proxy:仅 Surface + Font,运行 Label 控件。
  2. 对比 XGE proxy 与自定义 proxy 的渲染结果。
渲染代理 xui_proxy_t效果
图:渲染代理 xui_proxy_t渲染效果