arm-2d库详细介绍

1 概述

本文档解释了 ARM-2D 的基本概念。在我们开始体验Arm-2D时,你可能会有很多问题,比如:

  1. Arm-2D 是什么?

  2. 它能解决什么问题?

  3. 目标受众是谁?

  4. Arm-2D 由什么组成?

  5. 发展环境如何?

接下来的内容,将一一作答。

1.1 什么是arm-2d

如果您想在 Linux 中设计 GUI 应用程序,则不必直接面对硬件。Linux 生态系统为您提供了所有必要的软件组件,包括 GPU 驱动程序、 GUI 栈和许多方便的参考设计。

不幸的是,如果您是使用 Cortex-M 设备的嵌入式开发人员,则必须直接面对各种显示硬件。更糟糕的是,您可能要面对来自不同硬件厂商的各种非标准2D 图形加速器。许多 GUI 栈可用于嵌入式应用程序,但是大多数 GUI 栈并不能立即用于目标设备。因此,您必须首先完成移植工作。总之,在 Cortex-M 系统中使用 GUI 是可行的,但是在此之前还有很多底层的工作要做。

图1-1 GUI 中富嵌入式系统与约束嵌入式系统的生态系统比较

Arm-2D 不是重新发明图形用户界面或与现有的图形用户界面堆栈竞争。ARM-2D 想要解决的问题是如何为所有的 GUI 栈提供一个统一的低级硬件加速接口,这样高级软件服务提供商就可以不用为不断涌现的非标准硬件编写驱动程序。一旦 ARM-2D 成为图形用户界面供应商和芯片制造商之间的桥梁,每个人都可以做到最好。

图1-2典型嵌入式 GUI 系统的层次结构

Arm-2D 侧重于低级别的2D 图像处理,并为各种2D 加速器提供统一的软件接口。

1.2 目标受众

Arm-2d 的参与者有三种类型: GUI 服务提供商、硬件供应商和嵌入式软件开发商。

GUI服务

GUI服务提供商可以受益于ARM-2D,为常用硬件加速提供标准接口。GUI 服务提供商可以默认使用 Arm-2D 来获得低级加速。因此,他们不再需要为硬件编写驱动程序,而是专注于改进软件并为 VIP 客户提供定制服务。

硬件厂商

半导体制造商可以从 ARM-2D 中受益。为了节省学习新体系结构的时间,程序员希望在相同的体系结构下使用微控制器,在大多数情况下,这意味着使用 Cortex-M 处理器。由于设备使用相同的处理器架构,半导体制造商有动力引入专有的外围设备以实现差异化。引入专用于二维图形的加速器已成为新的趋势。在硬件差异化给终端用户带来好处的同时,也不可避免地引入了软件碎片化的问题。引入一个硬件抽象层来缓解这个问题是软件工程中常见的做法。Arm-2D 是用于各种2D 图形加速的抽象层。

在理想的情况下,芯片制造商只需要为他们的硬件加速器实现 ARM-2d 兼容驱动程序,这足以从主流 GUI 栈获得支持。

嵌入式软件开发人员

大多数嵌入式软件开发人员使用资源有限的设备。一个典型的系统具有小于64KB 的 FLASH 和4 ~ 32K 的 SRAM。作为参考,一个标准的低成本串行液晶显示器(320 * 240分辨率和65K 彩色)需要150KB 内存的显示缓冲区,这是负担不起的。

此外,对于这样的微控制器,大多数现有的 GUI 栈太昂贵,以至于无法使用内存占用。另一方面,许多 GUI 应用程序非常简单,甚至一些自制的实现也足以满足需求。在这种情况下,大多数现有的 GUI 堆栈都太重了。

当一个人想用这种资源受限的微控制器从头开始构建一个基于 GUI 的应用程序时,你要么完全放弃 GUI 的想法,要么在以下选项中做出权衡:

  1. 实现图形用户界面只使用简单的形状,如点,线,颜色块等

  2. 操作带宽低的轴承: 从 LCD 内部显示缓冲区读取像素,修改并写回

  3. 只复制/发送预先存储在 ROM 中的图片到 LCD,不需要任何处理

  4. 使用一种称为部分帧缓冲区的技术来实现时空交换

总而言之,在过去,很难在裸机环境中实现外观现代的 GUI。现在,Arm-2D 提供了一系列易于使用的 API,帮助用户使用所谓的部分帧缓冲区辅助服务实现所需的图形效果。值得一提的是,由 Arm-2D 引入的 PFB 支持的设计范例对于上层软件是透明的,这极大地简化了在裸金属环境中的应用程序开发,即用户可以设计应用程序,就好像有一个完整的帧缓冲区。

总之,Arm-2D 使许多设备(传统上不适合现代外观的 GUI)能够实现一个内存占用很小的现代外观的 GUI。

1.3 arm-2d库

作为一个起点,Arm-2D 为所有算法提供了默认的软件实现。这些软件实现主要是用 C 语言编写的,有时还包括一些本地汇编加速。这确保了 Arm-2D 可以直接在所有 Cortex-M 处理器上使用而不需要修改。

Helium加速

如果您使用的是 Armv8.1-M 处理器,比如 Cortex-M55,只要您启用编译选项的 Helium 支持,ARM-2D 库将自动使用 Helium 技术进行加速。

第三方执行

Arm-2D 已经提供了标准的方法来添加对各种第三方硬件加速器的支持。虽然现在不包括在内,在未来,我们将介绍模板,示例和文档,以显示如何添加对第三方硬件加速器的支持。

arm定制指令支持

Arm-2D 已经提供了标准的方法来添加对定制指令加速的2D 图像处理算法的支持。虽然不包括现在,在未来,我们将介绍模板,例子和文档,以显示如何。

1.4 范围和限制

ARM-2D 应该满足智能手表应用的要求:

  • 最多640 * 640分辨率,32位颜色

  • 60FPS刷新率

  • 提供缩放,旋转的支持

ARM-2D 应满足硬件受限环境下深度嵌入式应用的要求:

  • 一种典型的小于64K 闪存和4 ~ 32K SRAM 的单片机

  • 系统频率约为48MHZ或以上

  • 用于容忍低帧速范围从1 FPS 到30 FPS 的应用程序

  • 使用部分帧缓冲交付现代外观的 GUI (小至8 * 8 PFB,128字节,16位颜色),不限制支持的分辨率大小(用低帧速率交换 RAM)

相关限制如下:

该库原则上专注于 Cortex-M 处理器

该库应由以下编译器编译:

  • Arm Compiler 5
  • Arm Compiler 6
  • GCC
  • LLVM
  • IAR

该库聚焦于低级像素处理加速

  • 原则上,该库不提供为内容创建提供 API,例如绘图形状、文本显示等,但是提供简单的绘图点 API

  • 原则上,该库不提供创建 GUI 所必需的数据结构或相关算法,例如,元素树、 GUI 消息处理和树遍历算法

1.6 文件夹结构
文件夹和文件类型描述
Library文件夹此文件夹包含arm-2d库的源文件和头文件
Helper文件夹此文件夹包含 helper 函数/服务的源文件和头文件
documentation文件夹此文件夹包含所有文档
examples文件夹此文件夹包含所有示例代码/项目
READMEmd文档说明文档
how_to_deploy_the_arm_2d_librarymd文档一步一步的指导,帮助您将 Arm-2D 库部署到项目中
LICENSE许可证Apache 2.0许可证
tools文件夹此文件夹包含一些使用库的有用实用程序。例如img2c.py是一个python脚本,用于将指定图片转换为平铺数据结构。

2 基础知识

Arm-2D 定义了一些易于使用的基本数据结构,为各种图形资源提供了统一的描述方法,并简化了需要传递给2D 处理 API 的参数。本章将介绍一些使用 Arm-2D 库必须知道的基本概念和相应的数据结构。Arm-2D 系统地介绍了一个Boxing模型,以提供更复杂和易于使用的2D 图形操作。

2.1 region区域

Region是由 Location (左上角的坐标)和 Size 信息描述的矩形区域。

typedef struct arm_2d_region_t {
    implement_ex(arm_2d_location_t, tLocation);
    implement_ex(arm_2d_size_t, tSize);
} arm_2d_region_t;

图2-1有位置和面积的区域region

location位置

“区域region”的坐标由位矩形左上角的顶点定义。其数据结构如下:

typedef struct arm_2d_location_t {
    int16_t iX;
    int16_t iY;
} arm_2d_location_t;

与一般的笛卡儿坐标系不同,在图形中,Y 轴通常反射在相反的方向,这意味着 Y 坐标越低,Y 坐标越大。在后面将要介绍的 Boxing 模型中,我们将理解区域的坐标可以是负的,表示当前区域相对于其父区域起点的位置。

图2-2当位置为负坐标时。

如图2-2所示,当一个 region的 x 和 y 坐标都为负值时,它实际上在其父 Area 的外部(左上角)有相当大的面积。当我们尝试找到当前 region及其父 region的交集时,我们将发现只有部分区域是有效的。

size大小

区域region的大小信息由“高度”和“宽度”一起描述。数据结构的定义如下:

typedef struct arm_2d_size_t {
    int16_t iWidth;
    int16_t iHeight;
} arm_2d_size_t;

虽然有符号类型 int16_t 用于描述宽度和高度,但是负数是没有意义的,应该避免使用

2.2 boxing模型

所谓的boxing模型描述了区域之间的联系,这通常用于描述容器和可视元素之间的关系。

在 GUI 栈中,Boxing 模型通常涉及更复杂的内容,比如边框的宽度、容器边框内的边距、容器内元素之间的填充/距离等等。Arm-2D 并不关心这些细节,而只是描述容器和内部元素之间的简单关系。

绝对位置和相对位置

在 Arm-2d 中,我们将面板或窗口视为容器,面板和窗口的位置是它们在显示缓冲区中的坐标。我们称这种位置信息为绝对位置,它直接将显示缓冲区中的坐标描述为绝对位置。在图2-3中,面板(顶部容器)的坐标是绝对坐标。

容器内元素的坐标被描述为相对于父容器左上角的坐标。我们称这种位置为相对位置。除此之外,由于容器只是一个特殊的元素,因此容器嵌套成为可能。在图2-3中,最里面的两个区域region有相对位置。

图2-3绝对位置和相对位置的典型例子

如果一个区域region有绝对位置,它就是绝对区域; 类似地,如果一个区域region有相对位置,它就是相对区域。

图2-4绝对区域和相对区域的典型例子

当我们使用这些相对和绝对信息来执行视觉区域计算时,很容易从各种图形操作中排除那些实际上对用户不可见的区域,从而提高整体2D 处理性能(如图2-4所示)。

2.3 tile贴图

tile瓷砖是 Arm-2D 中各种2D 操作的最小单元。瓷砖数据结构由三部分组成:

  1. 瓷砖的特点

  2. 瓷砖的区域

  3. 瓷砖的指针

Tile 数据结构的 C 定义如下:

typedef struct arm_2d_tile_t arm_2d_tile_t;
struct arm_2d_tile_t {
    implement_ex(struct {
        uint8_t    bIsRoot              : 1;
        uint8_t    bHasEnforcedColour   : 1;
        uint8_t    bDerivedResource     : 1;
        uint8_t                         : 5;
        uint8_t                         : 8;
        uint8_t                         : 8;
        arm_2d_color_info_t    tColourInfo;
    }, tInfo);

    implement_ex(arm_2d_region_t, tRegion);

    union {
        /*! when bIsRoot is true, phwBuffer is available,
         *! otherwise ptParent is available
         */
        arm_2d_tile_t       *ptParent;
        uint8_t             *pchBuffer;
        uint16_t            *phwBuffer;
        uint32_t            *pwBuffer;

        intptr_t            nAddress;
    };
};

表2-1 arm_2d_tiles_t 中每个成员的功能

成员分类类型描述
bIsRoot特征信息bit-field这个位表示一个贴图是否是根贴图。如果目标贴图是根贴图,那么将包含一个指向显示缓冲区的指针的,且该位为1。如果目标贴图是子贴图,其中必须包含一个指向父节点的指针。
bHasEnforcedColour特征信息bit-field此位指示平铺是否显式包含像素颜色的描述符。当值为1,tColourInfo是有效的,否则视为包含无效信息。如果贴图被用作颜色转换操作的源贴图,这个位必须置为1,且tColourInfo必须包含有效的描述。对于大多数 Arm-2d 操作,当这个位为0时,Arm-2d API 将使用它自己对瓷砖颜色的隐式声明。比如说,arm_2d_rgb16_tile_copy()就有描述色彩的隐式声明即RGB16。因此,即使该值为1,操作上仍然使用隐式的RGB16。
bDerivedResource特征信息bit-field此位指示子贴图是否被用作资源当从现有的贴片创建资源时,必须将此位设置为“1”。该位只有在bIsRoot为0时才有效。
tColourInfo特征信息arm_2d_color_info_t当bHasEnforcedColour被置为1,tColourInfo则包含关于目标tile中使用颜色的有效描述符
tRegionregion区域arm_2d_region_t取决于给定tile的类型,tregion区域有不同的含义。
ptParent指针arm_2d_tile_t *当bIsRoot=0时,该指针用于父tile
pchBuffer指针uint8_t *bIsRoot=1时,此指针用于指向一个显示缓冲区,该缓冲区包含少于或等于8位的像素
phwBuffer指针int16_t *当bIsRoot=1时,此指针用于指向包含16位像素的显示缓冲区。
pwBuffer指针uint32_t*当bIsRoot=1时,此指针用于指向包含32位像素的显示缓冲区

2.3.1 根tile

根tile是一种直接包含显示缓冲区的tile,她的特征位bIsRoot是根据显示缓冲区中使用的像素类型设置的,对应的指针应该被使用。

值得强调的是,对于根 Tile,其 Location 坐标必须为(0,0) ; 否则,将认为它是非法的。

在 C99标准的帮助下,tile结构可以清晰、容易地初始化。下面的示例显示根tile:c_tPictureCMSISLogo

,表明一个存储在称为c_bmpCMSISLogo[]的常量数组中的RGBA8888位图。请注意,由于位图和tile结构类型被指定为常量,编译器很可能使用 ROM 而不是 RAM 来存储它们,并保持较小的 RAM 占用量。

/*! picture cmsis_logo */
extern const uint8_t c_bmpCMSISLogo[163 * 65 * sizeof(uint32_t)];
const static arm_2d_tile_t c_tPictureCMSISLogo = {
    .tRegion = {
        .tSize = {
            .iWidth = 163,
            .iHeight = 65
        },
    },
    .tInfo = {
        .bIsRoot = true,
        .bHasEnforcedColour = true,
        .tColourInfo = {
            .chScheme = ARM_2D_COLOUR_RGBA8888,
        },
    },
    .pwBuffer = (uint32_t *)c_bmpCMSISLogo,
};

事实上,在一些宏的帮助下,我们可以使用 Tile 来实现所谓的可视化层的概念:

#define __declare_tile(__NAME)                                      \
            extern const arm_2d_tile_t __NAME;
#define declare_tile(__NAME)            __declare_tile(__NAME)

#define __implement_tile(__NAME, __WIDTH, __HEIGHT, __TYPE)         \
            ARM_NOINIT static __TYPE                                \
                __NAME##Buffer[(__WIDTH) * (__HEIGHT)];             \
            const arm_2d_tile_t __NAME = {                          \
                .tRegion = {                                        \
                    .tSize = {(__WIDTH), (__HEIGHT)},               \
                },                                                  \
                .tInfo.bIsRoot = true,                              \
                .pchBuffer = (uint8_t *)__NAME##Buffer,             \
            }

#define implement_tile(__NAME, __WIDTH, __HEIGHT, __TYPE)           \
            __implement_tile(__NAME, __WIDTH, __HEIGHT, __TYPE)

例如,我们可以创建两个可视化图层,大小分别为100 * 100和200 * 50,并使用颜色arm_ 2d_color_rgb565_t 作为像素:

declare_tile(c_tLayerA)
implement_tile(c_tLayerA, 100, 100, arm_2d_color_rgb565_t);

declare_tile(c_tLayerB)
implement_tile(c_tLayerB, 200, 50, arm_2d_color_rgb565_t);

这些层存储在 RAM 中,作为2D 操作的源和目标。

注意,在上面提到的宏模板中,我们使用 ARM_NOINIT 来装饰显示缓冲区,其定义如下:

#ifndef ARM_NOINIT
#if     defined(__IS_COMPILER_ARM_COMPILER_5__)
#   define ARM_NOINIT           __attribute__( ( section( ".bss.noinit"),zero_init) )
#elif   defined(__IS_COMPILER_ARM_COMPILER_6__)
#   define ARM_NOINIT           __attribute__( ( section( ".bss.noinit")) )
#elif   defined(__IS_COMPILER_IAR__)
#   define ARM_NOINIT           __no_init
#elif   defined(__IS_COMPILER_GCC__) || defined(__IS_COMPILER_LLVM__)
#   define ARM_NOINIT           __attribute__(( __section__( ".bss.noinit")))
#else
#   define ARM_NOINIT
#endif
#endif

很明显,对于 ARM Compiler 5和 ARM Compiler 6,ARM_NOINIT把目标变量放入名为.bss.noinit的ZI节信息里面去,在脚本文件中,该节将被放置在具有UNINIT特性的执行区域里面。

LR_ROM __ROM_BASE __ROM_SIZE  {                           
    ...
    ; Reserve empty region for stack
    ARM_LIB_STACK __RAM1_BASE ALIGN 8 EMPTY __STACK_SIZE { 
    }

    RW_RAM1 +0 __RAM1_RW_SIZE {
        * (+RO-DATA)
        * (+RW +ZI)
    }

    RM_RAM_NOINIT +0 UNINIT {
        * (.bss.noinit)
    }

    ; Reserve empty region for heap
    ARM_LIB_HEAP  __HEAP_BASE ALIGN 8 EMPTY __HEAP_SIZE  { 
    }
    ...
}

2.3.2 子tile

给定任意一个tile,我们可以基于它推导出理论上无限数量的子tile,这些子tile被称为 Arm-2D 中的子tile。值得强调的是,可用于派生的tile不需要是根tile。子tile的bIsRoot 标志为0,这意味着指针 ptParent 指向其父 Tile。

子tile的位置信息用于指示它在父tile中的位置。这里的坐标是允许负数的。子tile的区域可以大于父tile的大小。这通常用于实现部分帧缓冲区。有关详情,请参阅第2.3.3节。

图2-3显示了一系列的子tile,以及它们在区域视图中的派生关系。

引入子tile可以大大简化 GUI 资源的存储和表示。聪明的设计师甚至可以将许多图像元素放在同一张图片中,并通过从不同位置创建不同大小的子tile来检索它们。在实践中,一个多级子tile在2D 操作中几乎没有性能损失。

2.3.3 部分帧缓冲区PFB

所谓的部分帧缓冲区是 Tile Child 方案的一种特殊用法。它为一个小的矩形显示缓冲区建立一个根 Tile,并派生一个与实际屏幕大小相同的子 Tile。实际上,上层的 GUI 软件使用 Child Tile (全屏大小)来绘制图形和混合视觉层。完成一个帧后,实际上保存像素信息的 PFB 被发送到 LCD 驱动程序进行刷新。由于 FPB 只覆盖了一个很小的区域,在大多数情况下,上述绘图过程将被判定为“不需要实际绘图”而跳过。为了显示整个屏幕,我们需要不断重复这个过程,并在每次迭代开始时调整 FPB 和 Child Tile 之间的相对位置。对于我们来说,它看起来像在屏幕上一行一行移动 FPB,如图2-4所示。

图2-4部分帧缓冲区的工作原理

更多细节显示在examples/benchmark目录中的专用示例项目中。

2.4 色彩

Arm-2D 为支持更多的颜色格式保留了足够的空间。引入了一种数据结构来描述给定瓷砖中使用的颜色格式。C 的定义如下:

/*! 
 * \brief enumerations for colour attributes
 */
enum {
    ARM_2D_COLOUR_SZ_1BIT = 0,            //!< 1 bit:black and white
    ARM_2D_COLOUR_SZ_2BIT = 1,            //!< 4 colours or 4 gray-levels
    ARM_2D_COLOUR_SZ_4BIT = 2,            //!< 16 colours or 16 gray-levels
    ARM_2D_COLOUR_SZ_8BIT = 3,            //!< 256 colours
    ARM_2D_COLOUR_SZ_16BIT = 4,           //!< 16bits
    ARM_2D_COLOUR_SZ_32BIT = 5,           //!< true colour

    ARM_2D_COLOUR_SZ_1BIT_msk =   ARM_2D_COLOUR_SZ_1BIT << 1,
    ARM_2D_COLOUR_SZ_2BIT_msk =   ARM_2D_COLOUR_SZ_2BIT << 1,
    ARM_2D_COLOUR_SZ_4BIT_msk =   ARM_2D_COLOUR_SZ_4BIT << 1,
    ARM_2D_COLOUR_SZ_8BIT_msk =   ARM_2D_COLOUR_SZ_8BIT << 1,
    ARM_2D_COLOUR_SZ_16BIT_msk =  ARM_2D_COLOUR_SZ_16BIT<< 1,
    ARM_2D_COLOUR_SZ_32BIT_msk =  ARM_2D_COLOUR_SZ_32BIT<< 1,
    ARM_2D_COLOUR_SZ_msk      =   (0x07 << 1),

    ARM_2D_COLOUR_LITTLE_ENDIAN       = 0,
    ARM_2D_COLOUR_BIG_ENDIAN          = 1,

    ARM_2D_COLOUR_LITTLE_ENDIAN_msk   = ARM_2D_COLOUR_LITTLE_ENDIAN << 4,
    ARM_2D_COLOUR_BIG_ENDIAN_msk      = ARM_2D_COLOUR_BIG_ENDIAN    << 4,

    ARM_2D_COLOUR_NO_ALPHA = 0,
    ARM_2D_COLOUR_HAS_ALPHA = 1,

    ARM_2D_COLOUR_NO_ALPHA_msk        = ARM_2D_COLOUR_NO_ALPHA      << 0,
    ARM_2D_COLOUR_HAS_ALPHA_msk       = ARM_2D_COLOUR_HAS_ALPHA     << 0,

    ARM_2D_COLOUR_VARIANT_pos = 5,
    ARM_2D_COLOUR_VARIANT_msk         = 0x07 << ARM_2D_COLOUR_VARIANT_pos,
};

/*!
 * \brief enumerations for colour types
 * 
 */
enum {
    ARM_2D_COLOUR_BIN         =   ARM_2D_COLOUR_SZ_1BIT_msk,
    ARM_2D_COLOUR_1BIT        =   ARM_2D_COLOUR_SZ_1BIT_msk,

    ARM_2D_COLOUR_8BIT        =   ARM_2D_COLOUR_SZ_8BIT_msk,
    ARM_2D_COLOUR_GRAY8       =   ARM_2D_COLOUR_SZ_8BIT_msk,

    ARM_2D_COLOUR_16BIT       =   ARM_2D_COLOUR_SZ_16BIT_msk,
    ARM_2D_COLOUR_RGB16       =   ARM_2D_COLOUR_SZ_16BIT_msk,
    ARM_2D_COLOUR_RGB565      =   ARM_2D_COLOUR_RGB16,

/*  won't support
    ARM_2D_COLOUR_RGB565_BE   =   ARM_2D_COLOUR_SZ_16BIT_msk        |
                                  ARM_2D_COLOUR_BIG_ENDIAN_msk      ,
 */

    ARM_2D_COLOUR_32BIT       =   ARM_2D_COLOUR_SZ_32BIT_msk        ,
    ARM_2D_COLOUR_RGB32       =   ARM_2D_COLOUR_SZ_32BIT_msk        ,

    ARM_2D_COLOUR_CCCN888     =   ARM_2D_COLOUR_RGB32               ,
    ARM_2D_COLOUR_CCCA8888    =   ARM_2D_COLOUR_SZ_32BIT_msk        |
                                  ARM_2D_COLOUR_HAS_ALPHA_msk       ,

    ARM_2D_COLOUR_RGB888      =   ARM_2D_COLOUR_CCCN888             ,
    ARM_2D_COLOUR_BGRA8888    =   ARM_2D_COLOUR_CCCA8888            ,

/* not supported yet
    ARM_2D_COLOUR_NCCC888     =   ARM_2D_COLOUR_RGB32               |
                                  ARM_2D_COLOUR_BIG_ENDIAN_msk      ,
    ARM_2D_COLOUR_ACCC8888    =   ARM_2D_COLOUR_SZ_32BIT_msk        |
                                  ARM_2D_COLOUR_HAS_ALPHA_msk       |
                                  ARM_2D_COLOUR_BIG_ENDIAN_msk      ,
*/
    ARM_2D_CHANNEL_8in32      =   ARM_2D_COLOUR_SZ_32BIT_msk        |
                                  ARM_2D_COLOUR_HAS_ALPHA_msk       |
                                  ARM_2D_COLOUR_VARIANT_msk   ,
};


/*!
 * \brief a type used as colour descriptor
 * 
 */
typedef union {
    struct {
        uint8_t bHasAlpha  : 1;     //!< whether the target colour has alpha channel
        uint8_t u3ColourSZ : 3;     //!< the size of the colour
        uint8_t bBigEndian : 1;     //!< whether the colour is stored in big endian
        uint8_t u3Variant  : 3;
    };
    uint8_t chScheme;
} arm_2d_color_info_t;

表2.2 arm_2d_colour_info_t的成员

成员类型描述
bHasAlphabit-fieldbHasAlpha是用来表明目标色彩格式是否包含alpha通道
u3ColourSZbit-fieldu3ColourSZ是用来表明每个像素的数据长度,有效值表示为:" ARM_2D_COLOUR_SZ_ "
bBigEndianbit-field用于指示像素是否存储在 Big-Endian 中
u3Variantbit-field在极少数情况下,在上述位字段引用一种以上颜色格式最多可以用来编码8种不同的变体
chSchemeuint8_t上述位字段的8位表示。相比之下,它非常有效。以ARM_2D_COLOUR_开头的枚举,表示Arm-2D库中当前支持的颜色格式。例如:ARM_2D_COLOUR_RGB565。

除了颜色格式描述符之外,Arm-2D 库的当前版本还定义了受支持的颜色格式的数据结构:

typedef union arm_2d_color_rgb565_t {
    uint16_t tValue;
    struct {
        uint16_t u5B : 5;
        uint16_t u6G : 6;
        uint16_t u5R : 5;
    };
} arm_2d_color_rgb565_t;

typedef union arm_2d_color_bgra8888_t {
    uint32_t tValue;
    struct {
        uint32_t u8B : 8;
        uint32_t u8G : 8;
        uint32_t u8R : 8;
        uint32_t u8A : 8;
    };
} arm_2d_color_bgra8888_t;

typedef union arm_2d_color_rgb888_t {
    uint32_t tValue;
    struct {
        uint32_t u8B : 8;
        uint32_t u8G : 8;
        uint32_t u8R : 8;
        uint32_t     : 8;
    };
} arm_2d_color_rgb888_t;

如上所示,arm-2d 以小端方式描述颜色格式,例如,BGRA8888表示蓝色通道是第一个字节,Alpha 通道是第三个字节。颜色格式 CCCA8888意味着阿尔法通道是第三个字节,有三个颜色通道的名称和顺序,我们不关心。彩色格式 CCCN888意味着8个 MSB 是未使用的(保留给 alpha) ,较低的3个字节用于存储彩色通道。

2.4 API使用模式

Arm-2D API 可用于同步模式和异步模式。实际上,Arm-2D 库是为异步工作而设计的,并且封装后以支持同步模式。

2.4.1 同步模式

同步模式也称为经典模式,在这种模式下,直到服务完成或发生错误时,函数调用才会返回。在 Arm-2D 库的当前版本中,所有示例都是以同步模式编写的。

2.4.2 异步模式

异步模式有利于事件驱动的设计范式,适用于大多数基于实时操作系统的应用程序和裸机系统中用原型线程和/或有限状态机编写的应用程序。异步模式的示例和文档将很快添加进来。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值