GPUPixel项目分析

GPUPixel项目分析 文章目录1. 整体架构概览2. 核心类架构分析2.1 OpenGL 上下文管理 (GPUPixelContext)2.2 帧缓冲区管理 (GPUPixelFramebuffer FramebufferFactory)GPUPixelFramebufferFramebufferFactory (对象池模式)2.3 Shader 程序管理 (GPUPixelProgram)2.4 输入源 (Source)Source 基类SourceImageSourceRawData2.5 输出目标 (Sink)Sink 基类SinkRender (通用渲染)SinkView (平台视图)SinkSurface (Android Surface)SinkRawData (数据输出)SinkRawYuv (YUV 输出优化)3. 工具类3.1 DispatchQueue3.2 数学工具 (math_toolbox)3.3 Util3.4 文件系统抽象 (filesystem.h)3.5 日志系统 (logging.h)4. 平台适配层4.1 宏定义4.2 Objective-C 桥接 (objc_view)5. 数据流示例图片处理流程相机数据处理流程YUV 数据直接输出6. 架构设计模式总结7. 优缺点分析优点缺点/待改进参考1. 整体架构概览GPUPixel 是一个基于 GPU 的图像处理框架采用过滤器链的设计模式整体架构分为以下几个核心层次┌─────────────────────────────────────────────────────┐ │ 应用层 (Sink/Source) │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │ SinkView│ │SinkRender│ │SourceImage│ │SourceRaw│ │ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ ├─────────────────────────────────────────────────────┤ │ 过滤器链 (Filter) │ │ │ ├─────────────────────────────────────────────────────┤ │ 核心层 (Core) │ │ ┌──────────────┐ ┌──────────────┐ ┌────────────┐ │ │ │GPUPixelContext│ │GPUPixelProgram│ │GPUPixelFBO │ │ │ └──────────────┘ └──────────────┘ └────────────┘ │ ├─────────────────────────────────────────────────────┤ │ 平台适配层 (Platform) │ │ ┌────────┬────────┬────────┬────────┬────────┐ │ │ │ iOS │ Mac │Android │Windows │ WASM │ │ │ └────────┴────────┴────────┴────────┴────────┘ │ └─────────────────────────────────────────────────────┘2. 核心类架构分析2.1 OpenGL 上下文管理 (GPUPixelContext)文件:gpupixel_context.h/cc这是整个框架的核心单例负责管理 OpenGL/EGL 上下文的生命周期。classGPUPixelContext{staticGPUPixelContext*GetInstance();// 单例获取voidSyncRunWithContext(std::functionvoid(void)func);// 在GL线程同步执行voidUseAsCurrent();// 切换为当前上下文FramebufferFactory*GetFramebufferFactory()const;// FBO工厂};多平台上下文创建iOS:EAGLContext(OpenGL ES 2.0)macOS:NSOpenGLContextAndroid: EGL (支持PBUFFER_BIT | WINDOW_BIT双模式)Windows/Linux: GLFW GLADWASM: WebGL 2.0关键设计使用DispatchQueue作为任务队列所有 GL 操作都在同一线程执行SyncRunWithContext确保线程安全持有FramebufferFactory统一管理 FBO 资源2.2 帧缓冲区管理 (GPUPixelFramebufferFramebufferFactory)GPUPixelFramebufferclassGPUPixelFramebuffer{uint32_ttexture_;// 纹理IDuint32_tframebuffer_;// FBO IDintwidth_,height_;voidActivate();// 绑定FBOvoidDeactivate();// 解绑FBO};FramebufferFactory (对象池模式)classFramebufferFactory{std::mapstd::string,std::shared_ptrGPUPixelFramebufferframebuffers_;std::mapstd::string,intframebuffer_type_counts_;// 根据参数生成唯一key复用已有的FBOstd::shared_ptrGPUPixelFramebufferCreateFramebuffer(...);};对象池设计通过GenerateUuid生成唯一标识复用相同尺寸和格式的 FBO避免频繁创建销毁。2.3 Shader 程序管理 (GPUPixelProgram)classGPUPixelGLProgram{uint32_tprogram_;// GL程序IDstaticstd::vectorGPUPixelGLProgram*programs_;// 所有程序实例// 编译链接着色器staticGPUPixelGLProgram*CreateWithShaderString(...);// Uniform 设置支持多种类型voidSetUniformValue(conststd::stringuniform_name,intvalue);voidSetUniformValue(conststd::stringuniform_name,Matrix4 value);// ... 重载多种类型};设计亮点静态programs_向量跟踪所有程序实例析构时检查是否还有其他程序在使用相同的 GL 程序 ID提供丰富的 Uniform 设置接口2.4 输入源 (Source)Source 基类classSource{std::mapstd::shared_ptrSink,intsinks_;// 输出目标列表std::shared_ptrGPUPixelFramebufferframebuffer_;RotationMode output_rotation_;// 添加输出目标std::shared_ptrSourceAddSink(std::shared_ptrSinksink);// 通知所有 Sink 更新voidDoUpdateSinks();};Source 作为生产者持有自己的输出 FBO并将数据推送给多个 Sink。SourceImageclassSourceImage:publicSource{std::vectoruint8_timage_bytes_;// 从文件创建staticstd::shared_ptrSourceImageCreate(conststd::string path);// 从内存缓冲区创建staticstd::shared_ptrSourceImageCreateFromBuffer(...);};功能加载图片到纹理作为过滤器链的起点。SourceRawDataclassSourceRawData:publicSource{uint32_ttexture_;// 原始数据纹理GPUPixelGLProgram*filter_program_;// 渲染程序// 处理原始帧数据voidProcessData(constuint8_t*data,intwidth,intheight,...);};功能处理来自相机或视频文件的原始帧数据。2.5 输出目标 (Sink)Sink 基类classSink{std::mapint,InputFrameBufferInfoinput_framebuffers_;intinput_count_;virtualvoidRender()0;// 渲染入口boolIsReady()const;// 检查所有输入是否就绪};Sink 作为消费者接收来自 Source 的输入进行最终处理或显示。SinkRender (通用渲染)classSinkRender:publicSink{GPUPixelGLProgram*display_program_;floatdisplay_vertices_[8];FillMode fill_mode_;voidRender()override;// 渲染到当前绑定的 FBO 或屏幕voidUpdateDisplayVertices();// 根据填充模式计算顶点坐标};功能将处理后的图像渲染到指定的视口支持多种填充模式PreserveAspectRatio: 保持宽高比可能有黑边PreserveAspectRatioAndFill: 保持宽高比并填充可能裁剪Stretch: 拉伸填充SinkView (平台视图)classSinkView:publicSink{void*render_view_;// ObjcView 实例// iOS/macOS 专用直接嵌入原生视图staticstd::shared_ptrSinkViewCreate(void*parent_view);};实现通过 Objective-C 桥接在 iOS/macOS 上直接使用ObjcView显示。SinkSurface (Android Surface)classSinkSurface:publicSink{ANativeWindow*native_window_;EGLSurface egl_surface_;voidSetNativeWindow(ANativeWindow*window,intwidth,intheight);voidRender()override;// 直接渲染到 Surface};Android 优化直接渲染到ANativeWindow避免 Java 层数据拷贝。SinkRawData (数据输出)classSinkRawData:publicSink{uint8_t*rgba_buffer_;uint8_t*yuv_buffer_;constuint8_t*GetRgbaBuffer();// 获取 RGBA 数据constuint8_t*GetI420Buffer();// 获取 I420 数据使用 libyuv 转换};功能将渲染结果读回内存供后续处理或编码使用。SinkRawYuv (YUV 输出优化)classSinkRawYuv:publicSink{// 使用着色器直接生成 YUV 数据voidRender()override;// 渲染到三个视口Y/U/Vconstuint8_t*GetI420Buffer();};优化通过一次渲染生成 Y、U、V 三个平面避免 CPU 色彩空间转换。3. 工具类3.1 DispatchQueueclassDispatchQueue{std::queuestd::functionvoid()taskQueue;std::thread worker;voidrunTask(std::functionvoid()task);// 同步执行任务boolisWorkerThread()const;// 判断是否在工作线程};用途确保所有 OpenGL 操作都在同一个线程执行避免多线程 GL 上下文问题。3.2 数学工具 (math_toolbox)提供Vector2、Matrix3、Matrix4等数学类型用于 Uniform 传递。3.3 UtilSetResourcePath/GetResourcePath: 资源路径管理StringFormat: 字符串格式化NowTimeMs: 时间戳IsAppleAppActive: iOS 应用状态检测3.4 文件系统抽象 (filesystem.h)#ifdefGPUPIXEL_USE_STD_FS#includefilesystemnamespacefsstd::filesystem;#else#includeghc/filesystem.hppnamespacefsghc::filesystem;#endif设计跨平台文件系统支持优先使用 C17 标准库否则使用第三方库。3.5 日志系统 (logging.h)#defineLOG_DEBUG(...)\std::cout[GPUPixel][ DEBUG ] gpupixel_format(__VA_ARGS__)std::endl;提供多级别日志宏可被外部项目替换。4. 平台适配层4.1 宏定义GPUPIXEL_IOS: iOS 平台GPUPIXEL_MAC: macOS 平台GPUPIXEL_ANDROID: Android 平台GPUPIXEL_WIN: Windows 平台GPUPIXEL_LINUX: Linux 平台GPUPIXEL_WASM: WebAssembly 平台GPUPIXEL_GLES_SHADER/GPUPIXEL_GL_SHADER: 着色器语法区分4.2 Objective-C 桥接 (objc_view)interfaceObjcView:UIView// iOS// 或interfaceObjcView:NSOpenGLView// macOS-(void)DoRender;-(void)SetInputFramebuffer:...;作用作为 C 和 Objective-C 之间的桥梁让 SinkView 能在原生视图上显示。5. 数据流示例图片处理流程// 1. 创建 SourceImageautoimageSourceImage::Create(photo.jpg);// 2. 添加滤镜 (未上传代码但架构支持)// auto filter BeautyFaceFilter::Create();// image-AddSink(filter);// 3. 创建输出目标autoviewSinkView::Create(parentView);// filter-AddSink(view);// 4. 触发渲染image-Render();// 或 filter-Render();相机数据处理流程// 1. 创建 RawData SourceautosourceSourceRawData::Create();// 2. 添加滤镜和输出autofilter...;autorenderSinkRender::Create();source-AddSink(filter)-AddSink(render);// 3. 每帧传入数据source-ProcessData(camera_frame,width,height,stride,type);YUV 数据直接输出autoyuvSinkSinkRawYuv::Create();filter-AddSink(yuvSink);// 获取 YUV 数据constuint8_t*i420yuvSink-GetI420Buffer();6. 架构设计模式总结模式应用单例GPUPixelContext对象池FramebufferFactory观察者Source 持有多个 Sink责任链过滤器链工厂方法Create()静态方法线程池DispatchQueue桥接ObjcView(C/ObjC)适配器各平台上下文创建7. 优缺点分析优点跨平台支持 iOS/macOS/Android/Windows/Linux/WASM高性能对象池复用、直接 Surface 渲染、NEON 优化线程安全所有 GL 操作统一线程灵活性可扩展的过滤器链设计缺点/待改进内存管理使用原始指针可能带来风险部分代码存在重复如纹理坐标数组Android 部分依赖 JNI 但代码中未完整展示参考https://blog.csdn.net/chenweiyu11962/article/details/147530040?ops_request_miscelastic_search_miscrequest_id04a38e856594dc217ebae97d968f8ca8biz_id0utm_mediumdistribute.pc_search_result.none-task-blog-2allsobaiduend~default-2-147530040-null-null.142v102pc_search_result_base4utm_termGPUPixel%20spm1018.2226.3001.4187