
1. 问题背景在 Android 图像渲染链路里常见现象是使用 DISPLAY_P3_PASSTHROUGH 时P3 测试图中的水印可见。只改成 EGL_GL_COLORSPACE_SRGB_KHR不做内容转换时水印有时仍可见。做了显式 DisplayP3 - sRGB 内容转换后水印明显变弱或不可见。在任务管理栏Recents的小窗预览里水印可能又看不见。这些现象并不矛盾核心在于“内容是否被正确色彩管理转换”。2. 关键概念2.1 内容转换Content Transform指在 shader 或渲染管线中对像素内容做显式色域变换例如sRGB - Display P3Display P3 - sRGB这是“真正改内容”的过程。2.2 输出目标标记Output Target Tag指 EGL surface 声明自身 colorspace例如EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXTEGL_GL_COLORSPACE_SRGB_KHR这是“声明输出如何被显示系统解释”不一定等价于内容已被正确转换。3. 三种典型路径及结果3.1 P3 Passthrough 路径Surface 声明为 P3 passthrough。若设备屏幕和系统链路支持 P3P3 内容更接近真实显示。依赖 P3 色差设计的水印通常可见。3.2 仅设置 sRGB 输出标记不做 P3-sRGB 内容转换内容仍可能是 P3 数值。显示端按 sRGB 解释出现“色彩失配”。这种失配可能带来偏色/饱和度变化反而把某些水印差异“放大”导致水印仍可见。这不是正确的色彩还原结果。3.3 显式 DisplayP3 - sRGB 内容转换 sRGB 输出先把 P3 内容正确映射到 sRGB再输出到 sRGB surface。对“依赖超出 sRGB 色域差异”的水印差异会被收敛。结果是水印显著减弱或不可见。这是工程上更可控、更一致的做法。4. 为什么 Recents 小窗里又看不见这通常不是应用内实时渲染结果变化而是系统任务缩略图机制导致Recents 里常显示的是系统快照不是应用当前 EGL surface 的实时复用。快照链路可能走 SDR/sRGB、缩放、压缩或色彩简化。因此 P3 细节包括 P3 隐水印在小窗里可能丢失。结论不要用任务管理栏缩略图判断 P3 渲染是否生效应以应用内实际画面为准。5. 工程实践建议如果目标是“非 P3 模式下尽量看不到 P3 水印”必须做显式 DisplayP3 - sRGB 内容转换。可叠加 EGL_GL_COLORSPACE_SRGB_KHR 作为输出侧保险。如果目标是“P3 真实显示”走 DISPLAY_P3_PASSTHROUGH。避免在该路径上再做 P3-sRGB 收敛。分支规则建议dst P3 src sRGBsRGB-P3dst ! P3 dst ! BT2020_PQ src P3P3-sRGBHDR/BT2020 路径单独处理不混入上述 SDR 分支。元数据完整性图片源的 dwColorGamut 必须在 decode/serialize/deserialize 过程中持续传递否则分支条件会误判。6. 常见误区“设了 EGL_GL_COLORSPACE_SRGB_KHR 就等于做了 P3-sRGB”错。它是输出目标声明不是内容变换本身。“任务栏小窗看不到说明应用内 P3 失败”不成立。Recents 快照链路与应用实时渲染链路不同。“水印可见就是色彩正确”不一定。失配显示也可能让水印更显眼。7. 一句话总结P3 显示问题的本质是“内容转换”和“输出标记”必须匹配。只改输出标记会产生不受控失配显式色彩转换才是可预期的工程解法。测试图