Android 的图形栈大家都熟悉:SurfaceFlinger + BufferQueue + ANativeWindow。鸿蒙也是类似的生产者-消费者模型,只是接口命名和实现细节有些不同。

作为 GPU 开发者,需要在 winsys 层对接系统窗口。Android 用 ANativeWindow_*,鸿蒙用 OH_NativeWindow_*,看着差不多,真移植起来发现坑不少。

在这里插入图片描述

一、核心接口映射

功能Android鸿蒙 OHOS 6.1
请求 BufferANativeWindow_dequeueBuffer()OH_NativeWindow_NativeWindowRequestBuffer()
提交 BufferANativeWindow_queueBuffer()OH_NativeWindow_NativeWindowFlushBuffer()
取消 BufferANativeWindow_cancelBuffer()OH_NativeWindow_NativeWindowAbortBuffer()
获取 BufferHandleANativeWindowBuffer_getHardwareBuffer()OH_NativeWindow_GetBufferHandleFromNative()
引用计数+1ANativeWindow_acquire()OH_NativeWindow_NativeObjectReference()
引用计数-1ANativeWindow_release()OH_NativeWindow_NativeObjectUnreference()

二、属性操作对比

Android:独立函数

ANativeWindow_setUsage(window, usage);
ANativeWindow_setBuffersDimensions(window, width, height);
ANativeWindow_setBuffersFormat(window, format);
ANativeWindow_setBuffersTransform(window, transform);
ANativeWindow_setSwapInterval(window, interval);

// 查询
int width, height;
ANativeWindow_query(window, ANATIVEWINDOW_QUERY_DEFAULT_WIDTH, &width);

鸿蒙:统一 HandleOpt

// 设置
OH_NativeWindow_NativeWindowHandleOpt(window, SET_USAGE, usage);
OH_NativeWindow_NativeWindowHandleOpt(window, SET_BUFFER_GEOMETRY, width, height);
OH_NativeWindow_NativeWindowHandleOpt(window, SET_FORMAT, format);
OH_NativeWindow_NativeWindowHandleOpt(window, SET_TRANSFORM, transform);

// 查询
int width, height;
OH_NativeWindow_NativeWindowHandleOpt(window, GET_BUFFER_GEOMETRY, &height, &width);

三、提交 Buffer 差异

Android

// 仅需 release fence
ANativeWindow_queueBuffer(window, buffer, release_fence);

鸿蒙

// 需要 release fence + Region 脏区
Region region = {
    .rects = nullptr,      // nullptr = 全屏
    .rectNumber = 0
};
OH_NativeWindow_NativeWindowFlushBuffer(window, buffer, release_fence, region);

四、NativeWindowOperation 枚举

CodeAndroid 等效参数
SET_BUFFER_GEOMETRYsetBuffersDimensionsint32_t width, int32_t height
GET_BUFFER_GEOMETRYquery width/heightint32_t *height, int32_t *width
SET_FORMATsetBuffersFormatint32_t format
GET_FORMATgetFormatint32_t *format
SET_USAGEsetUsageuint64_t usage
GET_USAGEquery usageuint64_t *usage
SET_TIMEOUTint32_t timeout (ms)
GET_TIMEOUTint32_t *timeout
SET_COLOR_GAMUTsetBuffersDataSpaceint32_t colorGamut
GET_COLOR_GAMUTgetBuffersDataSpaceint32_t *colorGamut
SET_TRANSFORMsetBuffersTransformint32_t transform
GET_TRANSFORMquery transformint32_t *transform
SET_UI_TIMESTAMPsetBuffersTimestampuint64_t timestamp
GET_BUFFERQUEUE_SIZEquery min undequeuedint32_t *size
SET_SOURCE_TYPEint32_t sourceType
GET_SOURCE_TYPEint32_t *sourceType
SET_APP_FRAMEWORK_TYPEchar *frameworkType
GET_APP_FRAMEWORK_TYPEchar **frameworkType
SET_HDR_WHITE_POINT_BRIGHTNESSfloat brightness
SET_SDR_WHITE_POINT_BRIGHTNESSfloat brightness
SET_DESIRED_PRESENT_TIMESTAMPint64_t timestamp

五、鸿蒙特有接口

接口功能
OH_NativeWindow_LockBuffer()CPU 锁定 Buffer 直接访问
OH_NativeWindow_UnlockAndFlushBuffer()CPU 解锁并提交
OH_NativeWindow_PreAllocBuffers()预分配 Buffer
OH_NativeWindow_CleanCache()清理 Buffer 缓存
OH_NativeWindow_NativeWindowAttachBuffer()Attach Buffer 到窗口
OH_NativeWindow_NativeWindowDetachBuffer()从窗口 Detach Buffer
OH_NativeWindow_GetSurfaceId()获取 SurfaceId
OH_NativeWindow_CreateNativeWindowFromSurfaceId()从 SurfaceId 创建窗口
OH_NativeWindow_WriteToParcel() / ReadFromParcel()IPC 序列化
OH_NativeWindow_GetLastFlushedBufferV2()获取最后提交的 Buffer
OH_NativeWindow_SetBufferHold()保持 Buffer 不被回收

六、BufferHandle 结构

Android:AHardwareBuffer

// opaque 结构,通过 API 访问
AHardwareBuffer_Desc desc;
AHardwareBuffer_describe(buffer, &desc);

鸿蒙:BufferHandle

// 明确定义,直接访问
typedef struct BufferHandle {
    int32_t fd;              // DMA-BUF fd
    uint32_t reserveInts;    // reserve 数组大小
    int32_t reserve[0];      // 变长数据:width, height, stride, format...
} BufferHandle;

// 获取方式
BufferHandle *handle = OH_NativeWindow_GetBufferHandleFromNative(buffer);
// 直接访问:handle->fd, handle->reserve[0]...

七、完整流程对比

Buffer 获取与提交

Android:

    ANativeWindow_dequeueBuffer()
            │
            ▼
    ┌───────────────┐
    │ acquire_fence │
    └───────┬───────┘
            │
            ▼
    GPU 渲染完成
            │
            ▼
    ANativeWindow_queueBuffer()
    (buffer, release_fence)


鸿蒙:

    OH_NativeWindow_NativeWindowRequestBuffer()
            │
            ▼
    ┌───────────────┐
    │ acquire_fence │
    └───────┬───────┘
            │
            ▼
    GPU 渲染完成
            │
            ▼
    OH_NativeWindow_NativeWindowFlushBuffer()
    (buffer, release_fence, Region)

八、HandleOpt 分发表实现

// foundation/graphic/graphic_surface/surface/src/native_window.cpp

static std::map<int, std::function<void(OHNativeWindow*, va_list)>> operationMap = {
    {SET_USAGE, HandleNativeWindowSetUsage},
    {SET_BUFFER_GEOMETRY, HandleNativeWindowSetBufferGeometry},
    {SET_FORMAT, HandleNativeWindowSetFormat},
    {SET_TIMEOUT, HandleNativeWindowSetTimeout},
    {SET_COLOR_GAMUT, HandleNativeWindowSetColorGamut},
    {SET_TRANSFORM, HandleNativeWindowSetTransform},
    {SET_UI_TIMESTAMP, HandleNativeWindowSetUiTimestamp},
    {SET_SOURCE_TYPE, HandleNativeWindowSetSurfaceSourceType},
    {SET_APP_FRAMEWORK_TYPE, HandleNativeWindowSetSurfaceAppFrameworkType},
    {SET_HDR_WHITE_POINT_BRIGHTNESS, HandleNativeWindowSetHdrWhitePointBrightness},
    {SET_SDR_WHITE_POINT_BRIGHTNESS, HandleNativeWindowSetSdrWhitePointBrightness},
    {SET_DESIRED_PRESENT_TIMESTAMP, HandleNativeWindowSetDesiredPresentTimestamp},
    {GET_USAGE, HandleNativeWindowGetUsage},
    {GET_BUFFER_GEOMETRY, HandleNativeWindowGetBufferGeometry},
    {GET_FORMAT, HandleNativeWindowGetFormat},
    {GET_TIMEOUT, HandleNativeWindowGetTimeout},
    {GET_COLOR_GAMUT, HandleNativeWindowGetColorGamut},
    {GET_TRANSFORM, HandleNativeWindowGetTransform},
    {GET_BUFFERQUEUE_SIZE, HandleNativeWindowGetBufferQueueSize},
    {GET_SOURCE_TYPE, HandleNativeWindowGetSurfaceSourceType},
    {GET_APP_FRAMEWORK_TYPE, HandleNativeWindowGetSurfaceAppFrameworkType},
};

int32_t OH_NativeWindow_NativeWindowHandleOpt(OHNativeWindow *window, int code, ...)
{
    va_list args;
    va_start(args, code);
    auto it = operationMap.find(code);
    if (it != operationMap.end()) {
        it->second(window, args);
    }
    va_end(args);
    return OHOS::GSERROR_OK;
}

九、头文件与链接库

Android鸿蒙
头文件<android/native_window.h><native_window/external_window.h>
<android/hardware_buffer.h><native_buffer/buffer_handle.h>
链接库-lui -lgui-lnative_window -lsurface.z

近期我将android gpu代码移植鸿蒙发现不少知识点,在此总结。后续会讲部分实现接口!

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐