blob: e9ae88f4af58907ff364b91d8d0b8c5679ab3d9e [file] [log] [blame]
<html devsite><head>
<title>实现图形</title>
<meta name="project_path" value="/_project.yaml"/>
<meta name="book_path" value="/_book.yaml"/>
</head>
<body>
<!--
Copyright 2017 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<p>要实现 Android 图形 HAL,请查看以下要求、实现详情和测试建议。</p>
<h2 id="requirements">要求</h2>
<p>Android 图形支持需要以下组件:</p>
<ul>
<li>EGL 驱动程序</li>
<li>OpenGL ES 1.x 驱动程序</li>
<li>OpenGL ES 2.0 驱动程序</li>
<li>OpenGL ES 3.x 驱动程序(可选)</li>
<li>Vulkan(可选)</li>
<li>Gralloc HAL 实现</li>
<li>Hardware Composer HAL 实现</li>
</ul>
<h2 id="implementation">实现</h2>
<h3 id="opengl_and_egl_drivers">OpenGL 和 EGL 驱动程序</h3>
<p>您必须为 EGL、OpenGL ES 1.x 和 OpenGL ES 2.0 提供驱动程序(对 OpenGL 3.x 的支持是可选的)。主要注意事项包括:</p>
<ul>
<li>GL 驱动程序必须稳定可靠且符合 OpenGL ES 标准。</li>
<li>请勿限制 GL 上下文的数量。由于 Android 允许应用在后台运行,并且会尝试使 GL 上下文保持活动状态,因此您不应限制驱动程序中的上下文数量。</li>
<li>通常可同时具有 20-30 个活动的 GL 上下文,因此请注意为每个上下文分配的内存量。</li>
<li>支持来自系统中其他组件(如媒体编解码器或相机)的 YV12 图像格式和其他 YUV 图像格式。</li>
<li>支持强制扩展程序:<code>GL_OES_texture_external</code><code>EGL_ANDROID_image_native_buffer</code><code>EGL_ANDROID_recordable</code>。另外,对于 Hardware Composer v1.1 及更高版本,还需要 <code>EGL_ANDROID_framebuffer_target</code> 扩展程序。</li>
</ul>
<p>我们还强烈建议支持 <code>EGL_ANDROID_blob_cache</code><code>EGL_KHR_fence_sync</code><code>EGL_KHR_wait_sync</code><code>EGL_ANDROID_native_fence_sync</code></p>
<p class="note"><strong>注意</strong>:呈现给应用开发者的 OpenGL API 与在设备上实现的 OpenGL 不同。应用不能直接访问 GL 驱动程序层,且必须通过 API 提供的接口。</p>
<h3 id="pre-rotation">预旋转</h3>
<p>许多硬件叠加层不支持旋转(即使支持,也会耗费很多处理能力);解决方案是在缓冲区到达 SurfaceFlinger 之前进行预转换。Android 在 <code>ANativeWindow</code> 中支持查询提示 (<code>NATIVE_WINDOW_TRANSFORM_HINT</code>),以表示 SurfaceFlinger 应用于缓冲区的最可能的转换。GL 驱动程序可以使用此提示在缓冲区到达 SurfaceFlinger 之前预转换缓冲区,以便当缓冲区到达时,可以正确转换。</p>
<p>例如,当接收到旋转 90 度的提示时,会生成一个矩阵并将其应用于缓冲区,以防止其从页面末尾运行。为了节省电量,请进行此预旋转。有关详请,请参见 <code>system/core/include/system/window.h</code> 中定义的 <code>ANativeWindow</code> 接口。</p>
<h3 id="gralloc_hal">Gralloc HAL</h3>
<p>图形内存分配器会分配图像生成器请求的内存。您可以在 <code>hardware/libhardware/include/hardware/gralloc.h</code> 中找到 HAL 的接口定义。</p>
<h3 id="protected_buffers">受保护的缓冲区</h3>
<p>Gralloc 使用标记 <code>GRALLOC_USAGE_PROTECTED</code> 允许仅通过受硬件保护的路径显示图形缓冲区。这些叠加平面是显示 DRM 内容的唯一途径(SurfaceFlinger 或 OpenGL ES 驱动程序无法访问受 DRM 保护的缓冲区)。</p>
<p>受 DRM 保护的视频只能在叠加平面上呈现。支持受保护内容的视频播放器必须使用 SurfaceView 实现。在不受保护的硬件上运行的软件无法读取或写入缓冲区;受硬件保护的路径必须显示在 Hardware Composer 叠加层上(也就是说,如果 Hardware Composer 切换到 OpenGL ES 合成,受保护的视频将从显示设备中消失)。</p>
<p>有关受保护内容的详细信息,请参阅 <a href="/devices/drm.html">DRM</a> 一文。</p>
<h3 id="hardware_composer_hal">Hardware Composer HAL</h3>
<p>SurfaceFlinger 使用 Hardware Composer HAL (HWC) 将 Surface 合成到屏幕。它可以抽象出叠加层和二维位块传送器等对象,并且有助于分载通常由 OpenGL 完成的一些工作。有关 HWC 的详细信息,请参阅<a href="/devices/graphics/implement-hwc.html">实现 Hardware Composer HAL</a> 一文。</p>
<h3 id="vsync">VSYNC</h3>
<p>VSYNC 可将某些事件同步到显示设备的刷新周期。应用始终在 VSYNC 边界上开始绘制,而 SurfaceFlinger 始终在 VSYNC 边界上进行合成。这样可以消除卡顿,并提升图形的视觉表现。有关 VSYNC 的详细信息,请参阅<a href="/devices/graphics/implement-vsync.html">实现 VSYNC</a> 一文。</p>
<h3 id="vulkan">Vulkan</h3>
<p>Vulkan 是用于高性能三维图形的低开销、跨平台 API。像 OpenGL ES 一样,Vulkan 会提供相应工具,以用于在应用中创建高品质的实时图形。Vulkan 的优势包括降低 CPU 开销和支持 <a href="https://www.khronos.org/spir">SPIR-V 二进制中间</a>语言。有关 Vulkan 的详细信息,请参阅<a href="/devices/graphics/implement-vulkan.html">实现 Vulkan</a> 一文。</p>
<h3 id="virtual_displays">虚拟显示设备</h3>
<p>Android 在 Hardware Composer v1.3 中添加了对虚拟显示设备的平台支持。虚拟显示设备合成类似于物理显示设备:在 prepare() 中描述输入层,SurfaceFlinger 进行 GPU 合成,然后在 set() 中将层和 GPU 帧缓冲区提供给 Hardware Composer。有关虚拟显示设备的详细信息,请参阅<a href="/devices/graphics/implement-vdisplays.html">实现虚拟显示设备</a>一文。</p>
<h2 id="testing">测试</h2>
<p>对于基准测试,请按阶段使用以下流程:</p>
<ul>
<li>规格设计阶段。<em></em>在最初选定设备时(例如使用不成熟的驱动程序时),使用预定义(固定)的时钟和工作负载来测量每秒渲染的帧数 (fps)。这可以让我们清楚地了解硬件功能。</li>
<li>开发阶段。<em></em>在驱动程序成熟后,使用一组固定的用户操作来测量动画中的可见卡顿数量。</li>
<li>量产阶段。<em></em>当设备已准备好投放市场时,增加工作负载,直到卡顿增加。确定当前时钟设置是否可以跟得上负载。这可以帮助您确定在何处减慢时钟并减少功耗。</li>
</ul>
<p>为了在规格设计阶段便于推究设备性能,可使用 <code>platform/frameworks/native/cmds/flatland/</code> 下的 Flatland 工具。Flatland 依靠固定时钟,并显示可通过基于合成的工作负载实现的吞吐量。Flatland 使用 gralloc 缓冲区来模拟多窗口情景,用 GL 填充窗口,然后测量合成情况。</p>
<p class="note"><strong>注意:</strong>Flatland 使用同步框架来测量时间,因此您的实现必须支持同步框架。</p>
</body></html>