Egloo 架构设计

187 阅读8分钟

Egloo 架构设计

Egloo 是一个基于 Kotlin Multiplatform 的 OpenGL ES 框架,提供了跨平台的图形渲染能力。

1. 架构概览

Egloo 采用分层架构设计,主要包含以下几个层次:

    graph TD
        A[应用层] --> B[场景层]
        B --> C[图形层]
        C --> D[渲染层]
        D --> E[核心层]
        E --> F[平台特定实现]
    
    subgraph "核心层"
        E1[EGL管理] --- E2[表面管理]
    end
    
    subgraph "渲染层"
        D1[着色器程序] --- D2[缓冲区管理] --- D3[纹理处理]
    end
    
    subgraph "图形层"
        C1[2D图形] --- C2[3D图形] --- C3[几何工具]
    end
    
    subgraph "场景层"
        B1[场景管理] --- B2[渲染顺序] --- B3[对象变换]
    end
    
    subgraph "平台特定实现"
        F1[Android JVM] --- F2[Android Native]
    end

上图展示了Egloo的整体架构和各层之间的关系。

1.1 核心层 (Core Layer)

核心层提供了与 OpenGL ES 和 EGL 交互的基础设施:

  • EGL 管理

    • EglCore:平台特定的 EGL 上下文管理实现
    • EglNativeCore:跨平台的 EGL 核心功能实现
    • Egloo:框架入口和工具类
  • 表面管理

    • EglSurface:基础渲染表面
    • EglWindowSurface:窗口渲染表面

1.2 渲染层 (Rendering Layer)

渲染层提供了图形渲染的核心组件:

  • 着色器程序

    • GlFlatProgram:基础着色器程序实现
  • 缓冲区管理

    • GlBuffer:通用缓冲区
    • GlShaderStorageBuffer:着色器存储缓冲区
  • 纹理处理

    • 纹理加载、管理和渲染

1.3 图形层 (Graphics Layer)

图形层提供了各种图形对象的实现:

  • 2D 图形

    • Gl2dDrawable:2D 图形基类
    • GlCircle:圆形
    • GlRect:矩形
    • GlRoundRect:圆角矩形
    • GlSquare:正方形
    • GlTriangle:三角形
    • GlPolygon:多边形
  • 3D 图形

    • Gl3dDrawable:3D 图形基类
  • 几何工具

    • PointF:点
    • RectF:矩形区域
    • IndexedPointF:索引点
    • IndexedSegmentF:索引线段

1.4 场景层 (Scene Layer)

场景层负责管理复杂的渲染场景:

  • 场景管理
    • 场景图管理
    • 渲染顺序控制
    • 对象变换

2. 多平台支持

Egloo 使用 Kotlin Multiplatform (KMP) 实现跨平台支持,通过 expect/actual 机制实现代码共享和平台特定实现的分离。

graph TD
    A[Kotlin Multiplatform] --> B[共享代码 commonMain]
    A --> C[Android JVM androidJvmMain]
    A --> D[Android Native androidNativeMain]
    
    B --> E[接口定义]
    B --> F[抽象类]
    B --> G[通用算法]
    
    C --> H[Android特定实现]
    D --> I[Native特定实现]
    
    E -.-> H
    E -.-> I
    F -.-> H
    F -.-> I

2.1 Kotlin Multiplatform 架构设计

Egloo 的 KMP 架构基于以下原则设计:

2.1.1 代码组织结构
  • 源集划分

    • commonMain: 包含所有平台共享的代码
    • androidJvmMain: Android JVM 平台特定实现
    • androidNativeMain: Android Native (C/C++) 平台特定实现
  • 依赖管理

    • 每个源集有独立的依赖声明
    • 共享源集依赖被所有平台继承
    • 平台特定源集可以添加特定依赖
2.1.2 平台抽象机制
  • expect/actual 声明

    • commonMain 中使用 expect 声明接口和类
    • 在平台特定源集中使用 actual 实现这些声明
    • 例如:GlShaderLoader 在 common 中声明,在各平台中实现
  • 接口抽象

    • 定义通用接口,由各平台实现
    • 允许平台特定优化,同时保持 API 一致性
2.1.3 互操作性
  • JVM 互操作

    • 与 Android SDK 和 Java 库的无缝集成
    • 使用 JNI 桥接 Java 和 Native 代码
  • Native 互操作

    • 使用 kotlinx.cinterop 与 C 库交互
    • 直接访问 OpenGL ES 和 EGL 的 Native API

2.2 共享代码 (commonMain)

  • 平台无关的核心实现

    • 数学库(矩阵、向量计算)
    • 图形基础组件(点、线、形状)
    • 渲染管线抽象
  • 通用的数据结构和算法

    • 缓冲区管理
    • 场景图算法
    • 资源管理
  • 接口定义和抽象类

    • OpenGL 操作抽象
    • 渲染组件接口
    • 平台服务接口

2.3 Android JVM (androidJvmMain)

  • Android 特定的 EGL/GL 实现

    • 使用 Android 的 GLES20EGL14 API
    • 与 Android 的 SurfaceViewTextureView 集成
  • 与 Android 系统的集成

    • 生命周期管理
    • 资源加载
    • 上下文访问
  • JVM 平台优化

    • 利用 JVM 垃圾回收
    • 线程管理
    • 异常处理

2.4 Android Native (androidNativeMain)

  • Native 层的 EGL/GL 实现

    • 直接调用 OpenGL ES 和 EGL 的 C API
    • 使用 kotlinx.cinterop 进行 C 函数调用
  • 32/64 位支持

    • 适配不同 CPU 架构
    • 内存对齐和指针操作
  • 性能优化

    • 减少 JNI 调用开销
    • 直接内存访问
    • 避免不必要的对象创建

3. 核心组件详解

Egloo 的核心组件设计遵循 OpenGL ES 的渲染流程,同时提供了更高级的抽象以简化开发。

classDiagram
    class GlContext {
        +create(): GlContext
        +makeCurrent(): Boolean
        +release(): Boolean
    }
    
    class GlProgram {
        -shaders: List<GlShader>
        -attributes: Map<String, Int>
        -uniforms: Map<String, Int>
        +use(): Boolean
        +getAttributeLocation(name: String): Int
        +getUniformLocation(name: String): Int
    }
    
    class GlShader {
        -type: Int
        -source: String
        +compile(): Boolean
    }
    
    class GlShaderLoader {
        +loadShaderSource(path: String): String
    }
    
    class GlTexture {
        -target: Int
        -unit: Int
        +bind(): Boolean
        +setParameter(pname: Int, param: Int): Boolean
    }
    
    class GlDrawable {
        +draw(program: GlProgram): Boolean
    }
    
    class GlScene {
        -drawables: List<GlDrawable>
        +addDrawable(drawable: GlDrawable): Boolean
        +draw(): Boolean
    }
    
    GlProgram --> GlShader: contains
    GlProgram --> GlShaderLoader: uses
    GlScene --> GlDrawable: contains
    GlDrawable --> GlProgram: uses
    GlDrawable --> GlTexture: may use
    GlContext --> GlProgram: manages
    GlContext --> GlTexture: manages

GlShaderLoader是对源码进行优化,支持res中glsl文件加载。

3.1 EGL 管理

EGL 是 OpenGL ES 与底层窗口系统之间的接口,负责创建和管理渲染上下文。

flowchart LR
    A[应用程序] --> B[EGL API]
    B --> C[窗口系统]
    B --> D[OpenGL ES API]
    D --> E[GPU]
    
    subgraph "Egloo EGL 管理"
        F[GlContext] --> G[EglCore]
        G --> H[EglSurface]
        H --> I[Native Window]
    end
3.1.1 GlContext

GlContext 是 Egloo 中 EGL 上下文的抽象,负责:

  • 创建和管理 OpenGL ES 上下文
  • 处理上下文的生命周期
  • 提供线程安全的上下文切换
3.1.2 EglCore

EglCore 封装了 EGL 的核心功能:

  • 配置 EGL 显示和上下文
  • 选择合适的 EGL 配置
  • 管理 EGL 资源的生命周期
3.1.3 EglSurface

EglSurface 表示渲染目标:

  • 可以是窗口表面(用于屏幕显示)
  • 可以是像素缓冲区(用于离屏渲染)
  • 处理帧缓冲区交换和同步

3.2 着色器程序

着色器程序是 OpenGL ES 渲染管线的核心,Egloo 提供了简化的着色器管理。

flowchart TD
    A[GlProgram] --> B[顶点着色器]
    A --> C[片段着色器]
    B --> D[编译]
    C --> E[编译]
    D --> F[链接程序]
    E --> F
    F --> G[使用程序]
    
    H[GlShaderLoader] --> B
    H --> C
3.2.1 GlProgram

GlProgram 封装了 OpenGL ES 程序对象:

  • 管理着色器的编译和链接
  • 提供属性和统一变量的位置查询
  • 简化程序的使用和资源管理
3.2.2 GlShader

GlShader 表示单个着色器:

  • 支持顶点和片段着色器
  • 处理着色器编译
  • 提供错误检查和日志
3.2.3 GlShaderLoader

GlShaderLoader 负责从不同来源加载着色器代码:

  • 从资源文件加载
  • 从字符串加载
  • 支持跨平台的资源访问

3.3 渲染对象

Egloo 提供了一系列渲染对象,用于构建复杂的场景。

flowchart LR
    A[GlScene] --> B[GlDrawable]
    B --> C[GlFlatDrawable]
    B --> D[GlTexturedDrawable]
    
    C --> E[GlRect]
    C --> F[GlTriangle]
    C --> G[GlCircle]
    
    D --> H[GlTexturedRect]
3.3.1 GlDrawable

GlDrawable 是所有可绘制对象的基类:

  • 定义绘制接口
  • 管理顶点数据
  • 处理变换和属性
3.3.2 GlScene

GlScene 管理多个可绘制对象:

  • 维护绘制顺序
  • 处理场景更新
  • 优化渲染性能
3.3.3 特定形状

Egloo 提供了常用形状的实现:

  • GlRect: 矩形
  • GlTriangle: 三角形
  • GlCircle: 圆形
  • GlTexturedRect: 纹理矩形

3.4 纹理管理

纹理是 OpenGL ES 中重要的资源类型,Egloo 简化了纹理的创建和使用。

flowchart TD
    A[GlTexture] --> B[创建纹理]
    B --> C[配置参数]
    C --> D[上传数据]
    D --> E[使用纹理]
    
    F[图像源] --> D
    G[GlTextureLoader] --> F
3.4.1 GlTexture

GlTexture 封装了 OpenGL ES 纹理对象:

  • 创建和绑定纹理
  • 设置纹理参数
  • 管理纹理单元
3.4.2 GlTextureLoader

GlTextureLoader 负责从不同来源加载纹理数据:

  • 从位图加载
  • 从资源文件加载
  • 支持不同的图像格式

4. 跨平台实现策略

Egloo 通过精心设计的抽象层次和平台特定实现,实现了跨平台的 OpenGL ES 渲染能力。

flowchart TD
    A[通用接口层] --> B[平台抽象层]
    B --> C[Android JVM 实现]
    B --> D[Android Native 实现]
    
    subgraph "通用接口层"
        A1[GlProgram] --- A2[GlDrawable] --- A3[GlScene]
    end
    
    subgraph "平台抽象层"
        B1[expect 声明] --- B2[平台接口]
    end
    
    subgraph "Android JVM 实现"
        C1[actual 实现] --- C2[Android API 调用]
    end
    
    subgraph "Android Native 实现"
        D1[actual 实现] --- D2[Native API 调用]
    end

4.1 共享代码策略

Egloo 采用以下策略来最大化代码共享:

  1. 接口驱动设计

    • 定义清晰的接口边界
    • 使用抽象类封装通用逻辑
    • 将平台特定代码隔离到实现类
  2. 依赖注入

    • 使用工厂模式创建平台特定实例
    • 运行时注入适当的实现
    • 避免硬编码依赖
  3. 预处理器指令

    • 使用 expect/actual 声明
    • 条件编译处理平台差异
    • 源集分离管理平台代码

4.2 平台特定优化

每个平台实现都针对其特性进行了优化:

4.2.1 Android JVM 优化
  • 利用 Android 图形 API 的高级功能
  • 与 Android 生命周期集成
  • 使用 Android 特定的内存管理策略
4.2.2 Android Native 优化
  • 直接内存操作减少开销
  • 避免 JNI 调用的频繁跨边界
  • 使用 Native 内存分配策略

5. 性能优化与最佳实践

Egloo 架构设计中包含了多项性能优化策略和最佳实践。

5.1 渲染性能优化

graph TD
    A[批处理渲染] --> B[减少状态切换]
    C[顶点缓冲对象] --> D[减少数据传输]
    E[着色器优化] --> F[减少计算复杂度]
    G[纹理管理] --> H[减少纹理切换]
  1. 批处理渲染

    • 合并相似绘制调用
    • 减少 OpenGL ES 状态切换
    • 优化绘制顺序
  2. 缓冲区管理

    • 使用顶点缓冲对象 (VBO)
    • 适当时使用索引缓冲对象 (IBO)
    • 减少缓冲区更新频率
  3. 着色器优化

    • 简化着色器计算
    • 避免条件分支
    • 使用内置函数
  4. 纹理管理

    • 纹理图集减少绑定切换
    • 合理设置纹理过滤和包装模式
    • 使用适当的纹理格式和大小

5.2 内存管理

  1. 资源生命周期

    • 及时释放不再使用的资源
    • 使用引用计数管理共享资源
    • 避免资源泄漏
  2. 内存分配策略

    • 减少渲染过程中的对象创建
    • 使用对象池重用临时对象
    • 避免频繁的垃圾回收
  3. 缓冲区策略

    • 预分配足够的缓冲区空间
    • 使用直接缓冲区减少复制
    • 合理设置缓冲区大小

5.3 多线程渲染

  1. 渲染线程

    • 将渲染操作与主线程分离
    • 确保 OpenGL ES 上下文正确共享
    • 处理线程间同步
  2. 资源加载

    • 异步加载纹理和着色器
    • 使用后台线程准备渲染数据
    • 实现资源加载进度反馈
  3. 线程安全

    • 保护共享资源访问
    • 避免跨线程 OpenGL ES 调用
    • 使用同步原语确保数据一致性

6. 总结

Egloo 的架构设计围绕以下核心原则展开:

  1. 跨平台兼容性

    • 使用 Kotlin Multiplatform 实现代码共享
    • 通过抽象隔离平台差异
    • 提供一致的 API 体验
  2. 模块化设计

    • 清晰的组件职责划分
    • 松耦合的模块依赖
    • 可扩展的插件架构
  3. 性能优先

    • 针对移动平台优化
    • 减少不必要的开销
    • 高效的资源管理
  4. 开发者友好

    • 简化的 API 设计
    • 全面的错误处理
    • 详细的文档和示例

通过这些设计原则,Egloo 提供了一个强大而灵活的 OpenGL ES 框架,适用于跨平台图形应用开发。

3. 设计原则

3.1 模块化

  • 每个功能模块都是独立的,具有明确的职责
  • 模块之间通过接口进行交互
  • 便于扩展和维护

3.2 抽象层次

  • 使用 expect/actual 处理平台差异
  • 通过接口抽象隔离平台特定实现
  • 提供统一的 API 接口

3.3 性能优化

  • 最小化 GL 状态切换
  • 优化缓冲区管理
  • 支持批量渲染

3.4 易用性

  • 提供简单直观的 API
  • 封装复杂的 GL 操作
  • 提供常用的图形组件

4. 扩展性

框架支持多种扩展方式:

  • 自定义着色器程序
  • 自定义图形对象
  • 自定义渲染管线
  • 场景图扩展

5. 工具支持

提供了多个实用工具:

  • 矩阵操作 (Matrix)
  • 缓冲区工具 (Buffers)
  • 类型转换
  • 调试支持