FirefoxOS の色反転問題

AndroidStick に FirefoxOS を乗せる時に引っかかった問題として,色反転問題があります.詳しく調べ切れていないのですが,JellyBeans をベースとする場合には通常使う色フォーマットが Android とは異なることで現れるようです.

Window の色フォーマット決定

色フォーマットは場面ごとに使う手段によって決まるため,ここでは Window に描画されるフォーマットについて扱います.Window 向けのフォーマットは Gonk 層との境界 gecko/widget/gonk/libdisplay/GonkDisplayJB.cpp にある GonkDisplayJB() の surfaceformat にて決められます.

GonkDisplayJB::GonkDisplayJB()
{
  :
    if (!err && mFBDevice) {
        :
        /* The emulator actually reports RGBA_8888, but EGL doesn't return
         * any matching configuration. We force RGBX here to fix it. */
        surfaceformat = HAL_PIXEL_FORMAT_RGBX_8888;
    }
    :
    if (!err && mHwc) {
        :
        surfaceformat = HAL_PIXEL_FORMAT_RGBA_8888;
    }
    :
}

ここでは,Framebuffer が open できたらまず RGBX_8888 を設定し,Hwcomposer が open できたら RGBA_8888 に設定しなおすようです.Hwcomposer は画面の全部または一部を反転・回転・拡縮などを制御する Android 実装機能ですが,FirefoxOS では API 1.1 以上でないと使えないようで,まだ API 1.0 がほとんどの状況で使えない場合が多いです.AndroidStick の Hwcomposer もそうでした.

つまり「Hwcomposerが使えない」場合は surfaceformat は RGBX_8888 が選択されることになります.これは 1pixel が 32bit で扱われるとともに, Red,Green,Blue と 8bit とずつ並ぶフォーマットです(最後は空の8bit).ちなみに RGBA_8888 は 最後が alpha 情報が入るフォーマット,BGRA_8888 は並びが Blue,Green,Red,Alpha と並ぶフォーマットです.

画面モードの選択

フォーマットは選択されましたが,実際に Gonk 層へは EGL ライブラリを通じて設定されます. EGL では FirefoxOS や Android が期待するフォーマット情報を渡し,それにマッチする画面モードを返します.

その中にビット幅も情報に含まれるのですが,その値を取得するのは gecko/widget/gonk/nsWindows.cpp にある ColorDepth() です.先ほどの surfaceformat を参照して決めているようですが...

static uint32_t
ColorDepth()
{
    switch (GetGonkDisplay()->surfaceformat) {
    case GGL_PIXEL_FORMAT_RGB_565:
     return 16;
    case GGL_PIXEL_FORMAT_RGBA_8888:
     return 32;
    }
    return 24; // GGL_PIXEL_FORMAT_RGBX_8888
}

先ほど surfaceformat は RGBX_8888 が選択されていたので 24 が戻ります.Android で実装される EGL が正しく 24bit で RGBX のモードを持っていれば正しく表示されるはずですが,そうでなければ期待しないモードに設定されてしまいます.その結果がこれ.

色反転homescreen

キツネさんが青い...(T_T)

どうも RGBX_8888, 24bit と指定される EGL には BGRA_8888 相当が選択されてしまったようで,初期の段階では Red と Blue が反転してしまう問題が起こってしまっていました.

EGL の仕組みを知らなかったこともあって,なぜこうなるかまでたどり着くのにかなり掛かりましたが,Hwcomposer が有効な場合と同じ「最初に設定した surfaceformat を RGBA_8888 に修正」することで EGL の持つ正しいモードに設定されて解決しました.

Gonk 層に期待すること

Gonk 層,つまり Linux Kernel (Config) や Driver や Android Library は Android をベースにしている場合,Android が動くようにチューニングされています.そのため,FirefoxOS を動かすと必ずしも Android とは動作条件や受け渡す情報が同じにならないため,想定していない状態に陥ると残念ながら期待通りには動作しません.

となると,Gonk 層は Android だけでなく FirefoxOS が期待する条件でも動くように実装されている必要があります.これは地道に「Gonk 層は何が期待されているのか」を探っていくしかないでしょうね...

 

 


コメント

タイトルとURLをコピーしました