三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

Windows下用VS2019编译CEF官方Demo,手把手搞定离屏渲染(OSR)环境

Windows下用VS2019编译CEF官方Demo,手把手搞定离屏渲染(OSR)环境

Windows平台CEF离屏渲染开发实战:从源码编译到透明绘制全解析

1. 环境准备与源码获取

在Windows平台上进行CEF(Chromium Embedded Framework)开发,首先需要搭建合适的开发环境。对于使用Visual Studio 2019的开发者来说,推荐安装以下组件:

  • Visual Studio 2019:确保已安装"使用C++的桌面开发"工作负载
  • CMake:版本3.15或更高,建议通过官方安装程序获取
  • Windows 10 SDK:至少安装10.0.18362.0版本
  • Git:用于获取CEF源码和相关工具

CEF官方提供了预编译的二进制包,可以从 CEF Builds 下载。对于离屏渲染开发,建议选择:

  • Standard Distribution:包含所有必要的库文件和示例
  • 版本选择:推荐使用最新的稳定分支(如branch 4664)
  • 架构匹配:根据项目需求选择32位或64位版本

下载完成后,解压到不含中文和空格的路径,例如D:\cef_binary_xxx。解压后的目录结构应包含:

cef_binary_xxx/ ├── CMakeLists.txt ├── Debug/ ├── include/ ├── libcef_dll/ ├── Release/ ├── Resources/ └── tests/

2. CMake工程生成与VS2019配置

2.1 CMake配置步骤

  1. 打开CMake GUI工具,设置源码路径为解压后的CEF目录

  2. 创建并指定一个构建目录(如D:\cef_build)

  3. 点击"Configure"按钮,在弹出的对话框中选择:

    • Generator:Visual Studio 16 2019
    • Optional platform:根据需求选择Win32或x64
  4. 等待配置完成后,确保以下关键选项被正确设置:

    选项名称推荐值说明
    BUILD_SHARED_LIBSOFF建议静态链接CEF
    CEF_RUNTIME_LIBRARY_FLAG/MT与VS运行时库匹配
    USE_SANDBOXOFF简化调试过程
  5. 点击"Generate"生成VS2019解决方案文件

2.2 Visual Studio工程调整

生成的解决方案通常包含多个项目,其中cefsimple和cefclient是最重要的两个示例程序。打开解决方案后:

  1. 将cefclient设为启动项目
  2. 检查项目属性确保:
    • C++语言标准:至少C++17
    • 运行库:与CMake配置一致(/MT或/MD)
    • 附加包含目录:正确包含CEF的include路径
  3. 解决可能的编译错误:
    • 缺少Windows SDK版本定义:在预处理器定义中添加_WIN32_WINNT=0x0A00
    • 链接错误:检查库目录是否包含CEF的lib路径
// 示例:解决Windows版本定义问题 #if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0A00 #undef _WIN32_WINNT #define _WIN32_WINNT 0x0A00 #endif

3. 离屏渲染模式配置与调试

3.1 启用离屏渲染

CEF的离屏渲染(OSR)模式可以通过两种方式启用:

  1. 命令行参数方式:

    // 在程序启动时添加参数 CefMainArgs main_args(hInstance); CefSettings settings; settings.windowless_rendering_enabled = true; // 关键设置 CefInitialize(main_args, settings, app, nullptr);
  2. 运行时参数方式:

    cefclient.exe --off-screen-rendering-enabled

3.2 常见渲染问题解决

初次启用OSR模式可能会遇到以下典型问题:

  • 边框线问题:由于示例代码默认添加了WS_BORDER样式 解决方案:修改OsrWindowWin::Create方法,移除窗口样式中的WS_BORDER
// 修改前 hwnd_ = CreateWindowEx(..., WS_BORDER | WS_CHILD | ...); // 修改后 hwnd_ = CreateWindowEx(..., WS_CHILD | ...); // 移除WS_BORDER
  • 渲染偏移问题:离屏缓冲区与显示尺寸不匹配 解决方案:确保CefRenderHandler的实现正确处理了视图尺寸
void MyRenderHandler::OnPaint(CefRefPtr<CefBrowser> browser, PaintElementType type, const RectList& dirtyRects, const void* buffer, int width, int height) { // 确保这里的width/height与视图尺寸匹配 if (view_width_ != width || view_height_ != height) { view_width_ = width; view_height_ = height; // 重新分配渲染资源... } // 处理渲染数据... }

4. 透明绘制高级配置

4.1 启用透明绘制

要实现透明背景的网页渲染,需要同时启用两个设置:

  1. 在启动参数中添加:

    cefclient.exe --transparent-painting-enabled --no-proxy-server
  2. 在代码中配置:

    CefSettings settings; settings.windowless_rendering_enabled = true; settings.background_color = CefColorSetARGB(0, 0, 0, 0); // 完全透明

4.2 透明绘制问题排查

当透明绘制出现异常色彩时,通常需要检查以下关键点:

  1. 混合函数设置:

    // 修改OpenGL混合函数 if (IsTransparent()) { glBlendFunc(GL_ONE, GL_ZERO); // 替代默认的GL_ONE_MINUS_SRC_ALPHA glEnable(GL_BLEND); }
  2. 缓冲区格式验证:

    // 确保创建了支持alpha通道的纹理 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
  3. 渲染管线检查:

    • 确认没有额外的清屏操作覆盖alpha通道
    • 验证着色器是否正确处理了透明像素

注意:透明绘制性能受显卡驱动影响较大,在不同硬件上可能表现不一致,建议进行多平台测试。

5. 工程优化与实用技巧

5.1 编译优化配置

为提高开发效率,推荐进行以下VS2019配置调整:

  • 并行编译:在项目属性 > C/C++ > General中设置"Multi-processor Compilation"
  • 预编译头:为大型项目创建预编译头文件
  • 增量链接:调试时启用增量链接加快构建速度

5.2 调试技巧

  1. CEF日志输出:

    CefSettings settings; settings.log_severity = LOGSEVERITY_VERBOSE; // 获取详细日志 settings.log_file = "cef_debug.log"; // 指定日志文件
  2. 远程调试:

    cefclient.exe --remote-debugging-port=9222

    然后在Chrome浏览器中访问localhost:9222进行调试

  3. 内存检查:

    // 在程序退出时调用 CefShutdown(); // 使用VS内存诊断工具检查泄漏 _CrtDumpMemoryLeaks();

5.3 性能优化建议

对于要求高性能的离屏渲染应用,考虑以下优化措施:

优化方向具体措施预期效果
渲染线程使用单独的渲染线程减少UI线程阻塞
纹理上传使用PBO(Pixel Buffer Object)加速GPU数据传输
更新区域只处理脏区域(dirtyRects)减少渲染工作量
资源加载预加载关键资源改善用户体验
// 示例:使用脏区域优化 void MyRenderHandler::OnPaint(...) { for (const CefRect& rect : dirtyRects) { // 只处理需要更新的区域 ProcessDirtyRect(buffer, width, rect); } }

在实际项目中,离屏渲染的调试往往需要结合GPU调试工具(如RenderDoc)和CEF内置的日志系统。一个常见的经验是:当遇到难以解释的渲染问题时,先简化场景到最基本的绘制调用,逐步添加复杂度直到问题重现。这种方法虽然耗时,但能有效定位深层次的渲染管线问题。

← 返回列表