Android Pixelflinger 研究

http://jianhuazhang2008.blog.163.com/blog/static/412242292010111113626221/

 

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章