ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Electron SharedTextureImportTextureInfo:共享纹理导入对象详解与源码级原理剖析

Electron SharedTextureImportTextureInfo:共享纹理导入对象详解与源码级原理剖析 Electron SharedTextureImportTextureInfo共享纹理导入对象详解与源码级原理剖析【免费下载链接】electron:electron: Build cross-platform desktop apps with JavaScript, HTML, and CSS项目地址: https://gitcode.com/GitHub_Trending/el/electron本文围绕 Electron 的SharedTextureImportTextureInfo对象展开——它是sharedTexture模块导入外部 GPU 共享纹理时必传的纹理描述信息textureInfo。读完后你将掌握该对象每个字段的完整取值与平台差异Windows NT HANDLE / macOS IOSurface / Linux dmabuf planes、它在主进程与渲染进程间的流转路径以及 Electron 底层如何用 ChromiumSharedImage基础设施把它变成可跨进程传递的VideoFrame。一、它是什么从「纹理描述」到「VideoFrame」的入口sharedTexture是 Electron 的实验性模块官方定位是将外部共享纹理导入 Electron 并转换为平台无关的 WebVideoFrame支持所有 Web 渲染系统且可跨 Electron 进程传递见 docs/api/shared-texture.md。其典型输入来源是开启webPreferences.offscreen.useSharedTexture后离屏渲染OSRpaint事件携带的OffscreenSharedTexture——该对象上的textureInfo字段就是一个SharedTextureImportTextureInfo见 docs/api/structures/offscreen-shared-texture.md 与 docs/api/web-contents.md 的paint事件说明。三条 API 入口都消费这个对象sharedTexture.importSharedTexture({ textureInfo, allReferencesReleased })管理式 API主进程调用返回SharedTextureImported由 Electron 统一跟踪各进程引用并在全部释放后回调sharedTexture.subtle.importSharedTexture(textureInfo)subtle API手动管理生命周期返回SharedTextureImportedSubtlesharedTexture.subtle.finishTransferSharedTexture(transfer)目标进程完成跨进程传输transfer对象内部同样携带像素格式、尺寸等元数据见 docs/api/structures/shared-texture-subtle.md。SharedTextureImportTextureInfo的完整字段定义如下原文见 docs/api/structures/shared-texture-import-texture-info.md{ pixelFormat: bgra, // 必填纹理像素格式 colorSpace: undefined, // 可选ColorSpace 对象 codedSize: { width: 1280, height: 720 }, // 必填共享纹理的完整尺寸 visibleRect: { x: 0, y: 0, width: 1280, height: 720 }, // 可选可见区域子集 timestamp: 123456, // 可选微秒时间戳 handle: { /* 平台句柄见下文 */ } // 必填SharedTextureHandle }二、字段逐项解析2.1pixelFormat六种受支持的纹理格式pixelFormat是字符串决定底层media::VideoPixelFormat与SharedImage的格式映射。官方文档列出的取值为取值含义bgra32bpp BGRA字节序单平面rgba32bpp RGBA字节序单平面rgbaf16半浮点 RGBAHalf float单平面nv1212bppY 平面后接 2x2 交错 UV 平面nv1616bppY 平面后接 2x1 交错 UV 平面p010le4:2:0 10-bit YUV小端Y 平面后接 2x2 交错 UV 平面从源码实现看字符串到内部枚举的映射在 electron_api_shared_texture.cc 的 gin Converter 中完成if (pixel_format_str bgra) out-pixel_format media::PIXEL_FORMAT_ARGB; else if (pixel_format_str rgba) out-pixel_format media::PIXEL_FORMAT_ABGR; else if (pixel_format_str rgbaf16) out-pixel_format media::PIXEL_FORMAT_RGBAF16; else if (pixel_format_str nv12) out-pixel_format media::PIXEL_FORMAT_NV12; else if (pixel_format_str nv16) out-pixel_format media::PIXEL_FORMAT_NV16; else if (pixel_format_str p010le) out-pixel_format media::PIXEL_FORMAT_P010LE; else return false; // 非法取值最终抛出 Invalid shared texture info object注意两点bgra对应的是media::PIXEL_FORMAT_ARGBChromium 命名习惯字节序仍以 B 打头字符串不匹配六种取值之一时Converter 直接返回false外层ImportSharedTexture随即抛出 TypeErrorInvalid shared texture info objectL707-L714。反向的枚举→字符串转换函数TransferVideoPixelFormatToString见 L136-L153它在跨进程传输startTransferSharedTexture时把格式序列进 transfer 对象。2.2colorSpace可选颜色空间colorSpace可选类型为 ColorSpace。源码中该字段缺省值为 sRGB——ImportSharedTextureInfo::color_space gfx::ColorSpace::CreateSRGB()L582解析在 L640。创建SharedImage时color_space会随格式一起传入sii-CreateSharedImage(...)L799-L802之后由SharedImage承载getVideoFrame()生成的VideoFrame再通过raw_frame-set_color_space(si-color_space())携带到 Web 层L259。因此做 HDR如p010le纹理导入时应显式传入对应颜色空间。2.3codedSize与visibleRect完整尺寸 vs 可见区域codedSizeSize必填共享纹理的完整编码尺寸对应源码gfx::Size coded_sizevisibleRectRectangle可选[0, 0, codedSize.width, codedSize.height]的子集常见情况下就是全区域。解析逻辑印证了这一点L636-L639dict.Get(codedSize, out-coded_size); if (!dict.Get(visibleRect, out-visible_rect)) { out-visible_rect gfx::Rect(out-coded_size); // 缺省即整个 codedSize }visible_rect随后原样传给media::VideoFrame::WrapSharedImage(...)L253-L257因此它直接影响最终VideoFrame中有效像素的范围——例如外部编码器输出带填充padding的缓冲时可用它裁剪出真实画面区域。2.4timestamp微秒时间戳可选number单位微秒会被反射到生成的VideoFrame上L257 的base::Microseconds(ist-timestamp)。内部注释称其为 the capture timestamp, microseconds since capture startL584-L585。对实时视频管线而言这个值可用于与音频时钟对齐、做帧调度判断。2.5handle平台相关的SharedTextureHandlehandle必填类型为 SharedTextureHandle按平台提供互斥的字段WindowsntHandleBuffer。必须是 NT HANDLE由CreateSharedHandle产生且必须是已经复制到当前进程的句柄文档特别指出rgba/bgra/rgbaf16格式的纹理句柄不带 keyed mutex而nv12格式带 keyed mutex。源码侧从 Buffer 中读取 8 字节指针值GetNativeHandleL650-L660导入时先DuplicateHandle出一个可托管副本再包装成gfx::DXGIHandleL717-L735——这正是设计文档强调的「非 NT HANDLE 是进程本地的Chromium 销毁GpuMemoryBuffer时会CloseHandle若传入旧式全局句柄会导致崩溃」见 shell/common/api/shared_texture/README.md 第 2 节。macOSioSurfaceBuffer持有IOSurfaceRef指针必须是当前进程中有效的 IOSurface。导入时对其做RETAIN递增引用计数而不是接管所有权L736-L746。LinuxnativePixmap对象包含planes每个平面dmabuf fd 一组的stride、offset、size、fd源码对每个fd执行dup()后再交给gfx::NativePixmapHandle避免进程已拥有该 fd 的所有权L747-L766modifier字符串形式的 GBM modifier传给 EGL 驱动supportsZeroCopyWebGpuImport是否支持零拷贝 WebGPU 导入L688-L697。一个关键前提原文档shared-texture.md与设计文档均强调调用importSharedTexture时句柄必须已经对当前进程可见。Chromium 的 IPC 层会透明处理跨进程句柄复制这也是 OSRpaint事件能直接用句柄的原因但如果你把textureInfo通过自己的 IPC 传给另一个进程再导入必须自行保证目标进程能访问该句柄例如 Windows 下先DuplicateHandle到目标进程。三、导入流程从 textureInfo 到 SharedImage主流程electron::api::shared_texture::ImportSharedTextureL707-L822按如下顺序执行解析textureInfogin::ConverterImportSharedTextureInfo::FromV8一次性取出pixelFormat、codedSize、visibleRect缺省补全为整个 codedSize、colorSpace、timestamp、id以及平台句柄构造gfx::GpuMemoryBufferHandle按平台把ntHandle先DuplicateHandle/ioSurfaceRETAIN/dmabuf planes逐 fddup包装起来见 L716-L767格式校验media::VideoPixelFormatToSharedImageFormat(pixel_format)失败即抛 Invalid shared texture buffer format创建 SharedImage取当前进程的SharedImageInterface主进程来自content::ImageTransportFactory渲染进程来自blink::SharedGpuContextL75-L88按平台选择 usage 标志Windows/macOS 额外启用WEBGPU_READ/WRITEL787-L798后调用sii-CreateSharedImage({format, coded_size, color_space, usage, SharedTextureVideoFrame}, gmb_handle)。失败时抛 Texture format or dimension might not be supported on current device or platform构建SharedTextureImported包装对象保存元数据与creation_sync_token返回带getVideoFrame/release/startTransferSharedTexture/getFrameCreationSyncToken/setReleaseSyncToken方法的 JS 字典L502-L553其结构见 docs/api/structures/shared-texture-imported.md。其中getVideoFrame()只在渲染进程可用主进程调用会抛 The VideoFrame cannot be created at current processL395-L399它内部走media::VideoFrame::WrapSharedImage(pixel_format, client_shared_image, creation_sync_token, release_callback, visible_rect, coded_size, Microseconds(timestamp))——这正是pixelFormat/codedSize/visibleRect/timestamp四个字段最终落到VideoFrame上的位置。四、跨进程传输中的 textureInfo 元数据textureInfo本身是可经 IPC 传递的纯数据句柄除外需自行保证目标进程可见。subtle 路径下startTransferSharedTexture()会导出ClientSharedImage并用 mojo 序列化为 base64 字符串同时把pixelFormat字符串化、codedSize、visibleRect、timestamp、syncToken一并打进 transfer 对象L267-L296目标进程调用finishTransferSharedTexture时这些字段再次通过同一个 Converter 被解析FinishTransferSharedTextureL824-L875经ImportSharedImage取回同一 Mailbox 的SharedImage引用并以WaitSyncToken等待源进程的 creation token 完成防止资源在目标侧真正取得 GPU 使用权之前被释放。生命周期保障是这套设计的核心难点完整论述见 shell/common/api/shared_texture/README.md两进程引用同一 Mailbox 时GPU 何时用完由SyncToken保证release()若发现帧已导入 WebGPU 管线会经gpu::ContextSupport::SignalSyncToken等待 GPU 完成后再触发回调通知你释放主进程中的源纹理。JS 层未手动release()直接 GC 时弱回调会记录错误日志并代为释放L362-L380。五、端到端示例来自测试规范仓库中 spec/api-shared-texture-spec.ts 给出了可复现的完整流程以 OSR 为纹理源// 1. 开启共享纹理的离屏窗口 const osr new BrowserWindow({ width: 128, height: 128, webPreferences: { offscreen: { useSharedTexture: true } } }); osr.webContents.setFrameRate(1); osr.webContents.on(paint, async (event) { const texture event.texture; // OffscreenSharedTexture if (!texture) return; // GPU 不可用时跳过 // 2. textureInfo 即 SharedTextureImportTextureInfo const imported sharedTexture.importSharedTexture({ textureInfo: texture.textureInfo, allReferencesReleased: () texture.release() // GPU 完成后释放源 }); // 3. 发送到渲染进程需先在渲染进程 setSharedTextureReceiver await sharedTexture.sendSharedTexture({ frame: win.webContents.mainFrame, importedSharedTexture: imported }); // 4. 源侧释放引用 imported.release(); });渲染进程侧用sharedTexture.setSharedTextureReceiver(callback)接收回调拿到的receivedSharedTextureData.importedSharedTexture上调用getVideoFrame()即可在 Web 渲染系统WebGL/WebGPU/video等中使用。适用前提与限制需注意sharedTexture全系列方法标注Experimental可能在未来版本移除importSharedTexture/sendSharedTexture仅主进程可用setSharedTextureReceiver仅渲染进程可用测试用例目前声明仅在 macOS arm64 上正常运行spec/api-shared-texture-spec.ts 的平台判断且 GPU 不可用时paint事件的texture为空示例代码对此做了跳过处理sendSharedTexture有 1000ms 超时调用前必须确保渲染进程已注册接收端且进程存活句柄可见性规则第二节是跨进程使用时的第一排查点。六、小结SharedTextureImportTextureInfo字段虽少却精确对应了「Chromium 导入外部 GPU 纹理所需的最小信息集」pixelFormat与handle决定内存如何被解读codedSize/visibleRect决定几何colorSpace/timestamp决定呈现与同步语义。理解它与SharedTextureHandle的平台差异、SharedTextureImported的引用计数与 SyncToken 生命周期机制后你就能在 Electron 中把自研编码器、摄像头管线或 OSR 的 GPU 输出以零拷贝方式接入 Web 标准渲染路径。【免费下载链接】electron:electron: Build cross-platform desktop apps with JavaScript, HTML, and CSS项目地址: https://gitcode.com/GitHub_Trending/el/electron创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表