您的位置:首页 > 编程语言 > Go语言

/LGC图形渲染/淺談 Google Skia 圖形處理引擎

2010-12-28 16:14 471 查看
淺談 Google Skia 圖形處理引擎

作者:
Jserv

日期:

2009-03-21

本文转自Jserv的博客,该文章介绍了 Google Skia 图形引擎的的历史背景、应用层面,并探讨其程序设计模型。

2008 年九月,Google 宣佈以改良過的 WebKit 為核心的網路瀏覽器 Chrome,
揭露了眾多新特徵,比方說嶄新的 [V8] JavaScript (ECMAscript) 執行引擎,
或許因為太亮眼,掩蔽了所使用另一個開放原始碼專案 [skia],後者是個 2D
向量圖形處理函式庫,包含字型、座標轉換,以及點陣圖都有高效能且簡潔的表
現。不僅用於 Google Chrome 瀏覽器,新興的 Android
開放手機平台也採用
skia 作為繪圖處理,搭配 OpenGL/ES 與特定的硬體特徵,強化顯示的效果,本
文簡介 Google Skia 的歷史背景、應用層面,並探討其程式設計模型。

Google 為了搭建 Open Handset Alliance (OHA) 的 Android
平台,布局極久,背後的百人研發團隊部份來自之前的併購案,其中兩項具指標性意義:

2005 年八月 17 日,收購美國 Android
公司,業務是手機軟體開發,這當然就是現在開放源碼 Android
計畫的前身

2005 年十一月,收購美國 Skia 公司,業務是向量繪圖軟體

被 Google 收購前的 Android
公司有著在 IT 產業為人所津津樂道的成果,本
文就不多談,而 Skia 公司自然也不是省油的燈。Skia Inc. 設立於北卡羅萊納
州的 Chapel HIll,由 Michael Reed (也稱為 Mike Reed) 所創辦,他在圖形
技術領域是相當頂尖的人物,與 Benoit Schillings (BeOS 主要開發者, Be
Inc. 第二位工程師,現為 Nokia CTO) 於專業手機軟體開發公司 OpenWave 共
事時,即在該公司產品 OpenWave Phone Suite Version 7.0 (以下簡稱 V7) 引
入精湛的向量圖形技術,在 50-300 kb 空間的實做中,提供了圖層 overlay 之
間 alpha blended 預覽、全功能向量矩陣轉換等進階功能。在加入 OpenWave
之前,Mike Reed 服務於 Apple,代表專案為 QuickDraw GX,主導進階圖形與
字型處理技術。Benoit Schillings 離開 OpenWave 轉任 Trolltech CTO 期間,
Mike Reed 開創了 Skia Inc.,該公司第一個產品為 SGL (Skia Graphics
Library),一個非常嚴謹的向量顯示引擎,能在低端設備比如手機、電視及其它
手持設備之上,呈現高品質的 2D 圖形。根據 LocalTechWire 的描述:

"Skia’s first product, SGL, is a portable graphics engine capable of
rendering state-of-the-art 2D graphics on low-end devices such as
mobile phones, TVs, and handhelds,” the Web site said. “SGL is
feature-set compatible with existing 2D standards, making it ideal to
serve as a back-end for public formats such as SVG, PDF, and
OpenVG. SGL is licensed as source or binary, and can be customized to
match specific HW/framebuffer requirements.”

自 2005 年 Skia 被 Google 收購後,一直相當神秘低調,直到 2007 年初,
Skia GL 相關的程式碼才被揭露,作為 Google Android
平台的圖形引擎,稍候
的 Google Chrome 瀏覽器也採用 Skia 引擎。隨著 Android
與 Chrome (開放
版本稱為 "Chromium") 兩大專案公佈程式碼後,skia 也一併公開原始程式碼,
以 Apache License v2 釋出 (注意,這意味著與 GPLv2 授權不相容),而
Android
與 Chrome 的程式碼庫中都有一份 [skia] 的複製,因需求不同,做了
部份的修改,比方說 Chrome 專案底下的 [chrome/trunk/src/skia],需要注意
的是,Skia 本身是不涉及底層環境,如 Linux Framebuffer 或 Gtk+ 銜接的處
理,這也是何以 Android
(透過 Linux Framebuffer) 與 Chrome (開發中的
Linux 版本使用 Gtk+) 需要提供一份修改,以便系統接軌,關於這方面的資訊,
可參照 Google Chromium 的開發日誌 Graphics in Google Chrome

相較於 Firefox 1.x,後繼的 Firefox 2.x/3.x 在圖形顯示方面有相當大的進
展,很大層面歸功於引入 Cario 向量圖形程式庫來處理網頁繪製,而 Skia 就
相當於扮演 Cairo 的角色,不過更輕量些。快速發展的 WebKit 儼然是從桌面
應用跨足移動裝置之網頁引擎解決方案的首選,Apple 與 Google 都有為數可觀
的全職工程師投入,拜網際網路的威力,也有其他廠商與團體個人積極投入開發,
目前 WebKit 支持的圖形函式庫計有 Cairo, Gtk+, Qt4, WxWidgets, Cg (Mac
的非開放原始碼函式庫), Skia 等等,並以 WebKit 中 class GraphicsContext
處理前述圖形函式庫的實做,可針對不同平台的特性,規範不同平台所需的巨集
與成員,詳情可參考程式碼
WebCore/platform/graphics/GraphicsContext.{h,cpp}。

Skia 以 C++ 實做,程式碼約八萬行,基本某些未知的因素,可參考的文件相當
有限,但 Chromium 的 SVN log 與程式碼則是現在最完整的文件,以下是其特
徵:

高度優化的軟體 rasteriser (module sgl/)

選擇性透過 OpenGL/ES,加速特定操作,如 shader 與 textures (module gl/)

動畫處理能力(module animator/)

內建 SVG 支援 (module (svg/)

內建若干 image codec,如 PNG, JPEG, GIF, BMP (modules images/)

內建文字處理,但缺乏泰文、藏文一類複雜文字處理的能力

效能特性:

對 image 與特定資料型態的 Copy-on-write

內部記憶體管理,謹慎地被免 fragmentation

Thread-safety

Skia 實做所需的相依性:

字型: FreeType (值得注意的是,FreeType 的維護者 David Turner 目前任職於 Google), Windows GDI

多執行緒模型: pthread, Windows threads

XML: expat, tinyxml

理解歷史背景,我們終於可以來作點有趣的事。首先,自 Google Code 取得
Skia 原始程式碼:

# svn co http://skia.googlecode.com/svn/trunk skia-trunk

乍看這「清爽」的目錄架構,很難想像過去這是商業軟體,或許 Google 有些
「不能說的秘密」,除了 samplecode/ 目錄若干的程式碼之外,就幾乎沒有充
分的文檔了。用 svn log 可瀏覽 Skia 開發的紀錄,"reed@android.com
" 就是
Mike Reed 本人,至今仍相當活躍地改良 Skia 的實做。編譯方式很單純,先看
看說明:(本文對應於 svn r130)

# cd skia-trunk

# make help

可得到以下說明:

Targets:

: out/libskia.a

bench: out/bench/bench

tests: out/tests/tests

clean: removes entire out/ directory

help: this text

Options: (after make, or in bash shell)

SKIA_DEBUG=true for debug build

SKIA_SCALAR=fixed for fixed-point build

SKIA_BUILD_FOR=mac for mac build (e.g. CG for image decoding)

期望的編譯輸出就是靜態函式庫 out/libskia.a,而 Skia 的內部運算可選擇浮
點數與定點 (fixed-point),不過筆者發現,目前尙未能透地選擇,但這不影響
我們理解 Skia 的使用與體驗其威力。以筆者使用的 GNU/Linux 來說,可下達
以下指令要求編譯:

# make SKIA_BUILD_FOR=linux

沒意外的話,系統就會乖乖的編譯:

compiling out/src/core/Sk64.o

compiling out/src/core/SkAlphaRuns.o

compiling out/src/core/SkBitmap.o

...

至於編譯 benchmark 程式,則可透過以下指令:

./out/bench/bench -o `pwd`

陸續會有類似以下的輸出:

running bench          polygon

running bench            lines

running bench           points

running bench          rrects3

running bench          rrects1

running bench           ovals3

running bench           ovals1

running bench           rects3

running bench           rects1

running bench    bitmap_index8

running bench      bitmap_4444

running bench       bitmap_565

running bench      bitmap_8888

可大概窺知 Skia 涵蓋的範疇,接著筆者就寫個小程式,使用 Skia C++ API: test-skia.c

/* Simple vector graphics demo utilizing Skia toolkit.

* Authored by Jim Huang <jserv.tw@gmail.com>

*/

#include "SkBitmap.h"

#include "SkDevice.h"

#include "SkPaint.h"

#include "SkRect.h"

#include "SkImageEncoder.h"

int main()

{

// Declare a raster bitmap, which has an integer width and height,

// and a format (config), and a pointer to the actual pixels.

// Bitmaps can be drawn into a SkCanvas, but they are also used to

// specify the target of a SkCanvas' drawing operations.

SkBitmap bitmap;

bitmap.setConfig(SkBitmap::kARGB_8888_Config, 200, 200);

bitmap.allocPixels();

// A Canvas encapsulates all of the state about drawing into a

// device (bitmap).  This includes a reference to the device itself,

// and a stack of matrix/clip values. For any given draw call (e.g.

// drawRect), the geometry of the object being drawn is transformed

// by the concatenation of all the matrices in the stack. The

// transformed geometry is clipped by the intersection of all of the

// clips in the stack.

SkCanvas canvas(new SkDevice(bitmap));

// SkPaint class holds the style and color information about how to

// draw geometries, text and bitmaps.

SkPaint paint;

// SkIRect holds four 32 bit integer coordinates for a rectangle.

SkRect r;

paint.setARGB(255, 255, 0, 0);

r.set(25, 25, 145, 145);

canvas.drawRect(r, paint); /** Draw the specified rectangle using

the specified paint. The rectangle

will be filled or stroked based on

the Style in the paint. */

paint.setARGB(255, 0, 255, 0);

r.offset(20, 20);

canvas.drawRect(r, paint);

paint.setARGB(255, 0, 0, 255);

r.offset(20, 20);

canvas.drawRect(r, paint);

// SkImageEncoder is the base class for encoding compressed images

// from a specific SkBitmap.

SkImageEncoder::EncodeFile("snapshot.png", bitmap,

SkImageEncoder::kPNG_Type,

/* Quality ranges from 0..100 */ 100);

return 0;

}

編譯方式:

g++ /

-I./include /

-I./include/core /

-I./include/images /

-Wall -o test-skia test-skia.c /

out/src/images/SkImageDecoder_libpng.o out/libskia.a /

-lpng -lpthread -g

筆者做了簡要的註解,大概可知曉 Sk 開頭的這些 API 的功用,而上述的範例
程式一開始就要求 Skia 配置畫布 (SkCanvas),接著透過一份 SkRect 物件 r,
給定 ARGB 的描述,使其有著不同的顏色,再來就是調整向量物件的位移並繪製。
正如前文提及,Skia 僅是繪圖引擎,並未如 Cairo 一般廣泛對應到 PDF, X11,
GDI 等等底層繪圖裝置,所以為了方便觀察繪圖結果,我們透過 Skia 內建的
image codec 來輸出 PNG 圖檔,所以執行前述編譯後的執行檔 "test-skia",
應該會得到以下圖檔:(本無外框與底色,但為了清楚於文章呈現,額外用繪圖
軟體追加).



疊合的三個不同色的矩形物件,就是透過以下 API 呼叫達成:

paint.setARGB(255, 0, 255, 0);

r.offset(20, 20);

canvas.drawRect(r, paint);

由於 Skia 與 Cairo 的同質性相當高,也可參照 Cairo documentation
建立所
需的背景知識。

原文地址:http://blog.linux.org.tw/~jserv/archives/002095.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: