1. Pixelflinger简介
Pixelflinger是Android系统中为 OpenGL ES引擎提供的一套软件渲染器(renderer)。系统启动时通过查看启动日志信息可以获取当前Pixelflinger的软件版本(代码)。 Pixelflinger软件版本随着Android版本的升级而提高,目前最新的版本为1.3(基于Android2.2系统)。
I/SurfaceFlinger( 1931): OpenGL informations:
I/SurfaceFlinger( 1931): vendor : Android
I/SurfaceFlinger( 1931): renderer : Android PixelFlinger 1.2
I/SurfaceFlinger( 1931): version : OpenGL ES-CM 1.0
Pixelflinger 作为软件渲染器,为OpenGL ES引擎提供了一系列基础绘图功能。这些功能包括定义各种颜色格式像素位置、画点画线、绘制矩形及三角形、填充纹理等等。由于OpenGL ES相当于一个状态机,配置OpenGL ES状态的函数也均由Pixelflinger提供。
Pixelflinger的源代码位于system/core/libpixelflinger。
头文件位于system/core/include/libpixelflinger和system/core/include/private/pixelflinger。
2. Pixelflinger主要数据结构
Pixelflinger在头文件 Ggl_context.h中定义了context_t结构体,用来存储OpenGL ES状态及数据上下文。context_t结构体中包含GGLContext、state_t、shade_t、iterators_t、 generated_vars_t等结构体。
GGLContext结构体中包含了Pixelflinger库可提供给上层调用的一些函数接口,包括画点画线、绘制多边形、配置OpenGL ES状态机等函数接口。
state_t结构体用来描述OpenGL ES状态机的状态,包含多个子结构体,每个子结构体均负责处理一部分OpenGL ES功能。包括存储贴图及纹理、裁剪操作、光栅操作、混合操作、景深操作、雾化操作等功能。
3. Pixelflinger初始化
gglInit(GGLContext** context)
为context_t分配空间;
调用ggl_init_context(c);
ggl_init_context(context_t* c)
调用ggl_init_procs(c),将state_t结构体的函数指针与Pixelflinger.cpp中的函数挂钩。
调用ggl_init_trap(c),配置OpenGL ES状态机的状态。
调用ggl_init_scanline(c),主要将scanline函数与context_t的接口挂钩。
调用ggl_init_texture(c),初始化纹理相关的状态。
调用ggl_init_picker(c),空函数。
调用ggl_init_raster(c),将Raster.cpp中的函数与state_t结构体的函数指针挂钩。
初始化其他信息及抖动矩阵
ggl_init_procs(context_t* c)
ggl_init_procs 使用GGL_INIT_PROC宏进行函数与函数指针的挂钩。
#define GGL_INIT_PROC(p, f) p.f = ggl_ ## f;
4. GGLContext提供的主要函数接口
直接渲染函数
pointx、linex、recti、trianglex
裁剪函数
scissor
设置纹理和色彩缓冲
activeTexture
bindTexture
colorBuffer
readBuffer
depthBuffer
bindTextureLod
功能控制开关
enable
disable
enableDisable
指定片段颜色
shadeModel
color4xv
指定颜色迭代器
colorGrad12xv
指定Z坐标迭代器
zGrad3xv
指定W坐标迭代器
wGrad3xv
指定雾迭代器与颜色
fogGrad3xv
fogColor3xv
指定混合参数
blendFunc
blendFuncSeparate
纹理环境(包括四种纹理REPLACE / MODULATE / DECAL / BLEND)
texEnvi
texEnvxv
纹理参数(包装及过滤)
texParameteri
纹理迭代器
texCoord2i
texCoord2x
为纹理ST坐标使用块浮点
texCoordGradScale8xv
texGeni
屏蔽函数
colorMask
depthMask
stencilMask
alpha函数
alphaFuncx
景深函数
depthFunc
逻辑操作接口
logicOp
清除函数
clear
clearColorx
clearDepthx
clearStencil
framebuffer操作
copyPixels
rasterPos2x
rasterPos2i
5. Pixelflinger支持的颜色格式
Pixelflinger在Format.cpp中定义 了所支持的颜色格式及像素的位置,常用的颜色格式主要有RGBA8888、RGBX8888、RGB565、BGRA8888。从结构体中可以看 出,Alpha通道位于32-24位,属于高位,可见RGBA8888使用的是大端顺序。这里定义的颜色格式只能够被ANdroid的OpenGL ES使用,和通过Canvas绘制的图像无关。
static GGLFormat const gPixelFormatInfos[] =
{ // Alpha Red Green Blue
{ 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE
{ 4, 32, {{32,24, 8, 0, 16, 8, 24,16 }}, GGL_RGBA }, // PIXEL_FORMAT_RGBA_8888
{ 4, 24, {{ 0, 0, 8, 0, 16, 8, 24,16 }}, GGL_RGB }, // PIXEL_FORMAT_RGBX_8888
{ 3, 24, {{ 0, 0, 8, 0, 16, 8, 24,16 }}, GGL_RGB }, // PIXEL_FORMAT_RGB_888
{ 2, 16, {{ 0, 0, 16,11, 11, 5, 5, 0 }}, GGL_RGB }, // PIXEL_FORMAT_RGB_565
{ 4, 32, {{32,24, 24,16, 16, 8, 8, 0 }}, GGL_RGBA }, // PIXEL_FORMAT_BGRA_8888
{ 2, 16, {{ 1, 0, 16,11, 11, 6, 6, 1 }}, GGL_RGBA }, // PIXEL_FORMAT_RGBA_5551
{ 2, 16, {{ 4, 0, 16,12, 12, 8, 8, 4 }}, GGL_RGBA }, // PIXEL_FORMAT_RGBA_4444
{ 1, 8, {{ 8, 0, 0, 0, 0, 0, 0, 0 }}, GGL_ALPHA}, // PIXEL_FORMAT_A8
{ 1, 8, {{ 0, 0, 8, 0, 8, 0, 8, 0 }}, GGL_LUMINANCE},//PIXEL_FORMAT_L8
{ 2, 16, {{16, 8, 8, 0, 8, 0, 8, 0 }}, GGL_LUMINANCE_ALPHA},// PIXEL_FORMAT_LA_88
{ 1, 8, {{ 0, 0, 8, 5, 5, 2, 2, 0 }}, GGL_RGB }, // PIXEL_FORMAT_RGB_332
{ 1, 16, {{ 0, 8, 0, 8, 0, 8, 0, 0 }}, GGL_Y_CB_CR_SP },// PIXEL_FORMAT_YCbCr_422_SP
{ 1, 12, {{ 0, 8, 0, 8, 0, 8, 0, 0 }}, GGL_Y_CB_CR_SP },// PIXEL_FORMAT_YCbCr_420_SP
{ 1, 16, {{ 0, 8, 0, 8, 0, 8, 0, 0 }}, GGL_Y_CB_CR_P }, // PIXEL_FORMAT_YCbCr_422_P
{ 1, 12, {{ 0, 8, 0, 8, 0, 8, 0, 0 }}, GGL_Y_CB_CR_P }, // PIXEL_FORMAT_YCbCr_420_P
{ 1, 16, {{ 0, 8, 0, 8, 0, 8, 0, 0 }}, GGL_Y_CB_CR_I }, // PIXEL_FORMAT_YCbCr_422_I
{ 1, 12, {{ 0, 8, 0, 8, 0, 8, 0, 0 }}, GGL_Y_CB_CR_I }, // PIXEL_FORMAT_YCbCr_420_I
{ 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE
{ 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE
{ 2, 16, {{ 0, 0, 16, 0, 0, 0, 0, 0 }}, GGL_DEPTH_COMPONENT},
{ 1, 8, {{ 8, 0, 0, 0, 0, 0, 0, 0 }}, GGL_STENCIL_INDEX },
{ 4, 24, {{ 0, 0, 24, 0, 0, 0, 0, 0 }}, GGL_DEPTH_COMPONENT},
{ 4, 8, {{ 32,24, 0, 0, 0, 0, 0, 0 }}, GGL_STENCIL_INDEX },
};
6. Pixelflinger的优化
1)通过优化context_t存储空间,保证cache对齐以优化性能。context_t是Pixelflinger中最常用,最大的一个数据结构。
void* const base = malloc(sizeof(context_t) + 32);
context_t *c = (context_t *)((ptrdiff_t(base)+31) & ~0x1FL);
ggl_init_context(c);
2)通过Android.mk中的编译选项优化
ifeq ($(TARGET_ARCH),arm)
# special optimization flags for pixelflinger
PIXELFLINGER_CFLAGS += -fstrict-aliasing -fomit-frame-pointer
endif
-fstrict-aliasing选项表示编译器不会将不同类型的对象指向同一个地址。
-fomit-frame-pointer选项可以使编译器在函数调用中节省fp寄存器以提高效率。
3)通过用汇编替代C语言函数直接优化性能
ifeq ($(TARGET_ARCH),arm)
PIXELFLINGER_SRC_FILES += t32cb16blend.S
endif
4)通过对ARM不同版本进行特殊优化
ifeq ($(TARGET_ARCH),arm)
LOCAL_ASFLAGS := -march=armv6
LOCAL_SRC_FILES := rotate90CW_4x4_16v6.S
LOCAL_MODULE := libpixelflinger_armv6
include $(BUILD_STATIC_LIBRARY)
endif
rotate90CW_4x4_16v6:
// r0 = dst
// r1 = src
// r2 = dst stride in pixels
// r3 = src stride in pixels
stmfd sp!, {r4,r5, r6,r7, r8,r9, r10,r11, lr}
add r14, r3, r3
add r12, r2, r2
ldrd r2, r3, [r1], r14
ldrd r4, r5, [r1], r14
ldrd r6, r7, [r1], r14
ldrd r8, r9, [r1]
pkhbt r10, r8, r6, lsl #16
pkhbt r11, r4, r2, lsl #16
strd r10, r11, [r0], r12
pkhtb r10, r6, r8, asr #16
pkhtb r11, r2, r4, asr #16
strd r10, r11, [r0], r12
pkhbt r10, r9, r7, lsl #16
pkhbt r11, r5, r3, lsl #16
strd r10, r11, [r0], r12
pkhtb r10, r7, r9, asr #16
pkhtb r11, r3, r5, asr #16
strd r10, r11, [r0]
ldmfd sp!, {r4,r5, r6,r7, r8,r9, r10,r11, pc}
rotate90CW_4x4_16v6这个函数中使用了ARMv6架构才支持的pkhtb指令,以提高处理速度。
5)system/core/libpixelflinger/codeflinger中用C语言通过填充机器码的形式实现了一些汇编操作,可以动态生成汇编函数。
6)网上有一些开源项目,通过使用ARMv7架构的Neon协处理器对性能进行优化。
http://code.google.com/p/0xdroid/issues/detail?id=57
Rockie Cheng