Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

TRAVEO™ T2G MCU: 高い水平解像度のレンダリング – KBA234941

TRAVEO™ T2G MCU: 高い水平解像度のレンダリング – KBA234941

IFX_Publisher1
Community Manager
Community Manager
Community Manager
250 sign-ins First comment on KBA 250 replies posted

TRAVEO™ T2G MCU: 高い水平解像度のレンダリング – KBA234941

Translated by: 

Original KBA: TRAVEO™ T2G MCU: Rendering high horizontal resolutions – KBA234941

バージョン: **

このKBAでは、ラインベース操作(LBO)モードでサポートされている最大レンダリングサイズよりも大きいレンダリング解像度(例として、2880x1080ピクセル)について下記に方法を説明します。

T2G-Cデバイスでサポートされている最大水平レンダリング解像度は、サポートできるディスプレイ解像度よりも低くなっています。大きなディスプレイは(新しいコンテンツをレンダリングせずに)複数の静止画像でのみ埋めることができますが、このKBAでは、このような高解像度ディスプレイのディスプレイコンテンツ全体をレンダリングする必要がある場合の可能な解決策について説明します。

1.1   高解像度をレンダリングする方法

高水平解像度のディスプレイをサポートするための1つの可能なオプションとしては、設計により複数の範囲(ウィンドウ)にディスプレイビューを分割し、それらを個別にレンダリングすることです。この場合、オンザフライ(OTF)レンダリングは、更新レートが異なる従来の(ダブルバッファー)レンダリングされたウィンドウと混在させることができます。背景画像は、3番目のウィンドウで表示できます。

MohammedA_41_0-1649241292447.png

 

このKBAは、コンテンツから独立した複数の領域をレンダリングする可能性について説明しています(HMIデザインの分割なし)。ドライバとハードウェアは、部分的にレンダリングされた画像が完全に一致することを保証します。主なアイデアは、以下に示すように、すべての塗りつぶし要素とブリット要素を使用してレンダリング関数を2回呼び出すことです。

MohammedA_41_1-1649241329323.png
 

void main()
{
    split_pos = w / 2; //example only
    init();
    while(not_finised)
    {
        render_part(ctx0, target0, 0, split_pos, h );
        render_part(ctx1, target1, split_pos, w - split_pos, h );
    }
}

レンダリング機能は下記の通り:

void render_part(CYGFX_BE_CONTEXT ctx, CYGFX_BE_TARGET target, int split_pos, int wp, int h )
{
    CyGfx_BeBindSurface(ctx, CYGFX_BE_TARGET_STORE | CYGFX_BE_TARGET_DST, target);
    CyGfx_BeFill(ctx, 0, 0, wp, h);
    for (i = 0; i < objects; i++)
    {
        CyGfx_BeBindSurface(ctx, CYGFX_BE_TARGET_SRC, object[i].surf);
        CyGfx_BeBlt(ctx, object[i].x - split_pos, object[i].y);
    }
}
注釈:         このサンプルコードは、単純なコピー操作のみを示しています。回転、スケーリング、および同様の関数には、ソースマトリックスが必要です。 split_posオフセットは、この行列の計算に含めることができます。

ドライバは、左または右の領域に必要のない操作を分類します。両方の領域に影響を与える操作は、両方の領域でレンダリングされますが、必要なピクセル数のみが使用されます。

1.1.1        ウィンドウを分割する方法

ウィンドウを分割するための4つの推奨方法を次に示します。 次の手順は、画像ベースの操作(IBO)およびLBOレンダリング方法で使用できます。 OTFバージョンにはLBOレンダリングが必要であることに注意してください。

1.1.1.1 2つのOTFウィンドウ

この方法では、2つの異なるラインバッファ(surfwin0とsurfwin1)と2つの異なるCmdSeqタスク(ctx0とctx1)を備えた2つのOTFウィンドウが必要です。 両方のウィンドウが同じディスプレイに接続されています。 2番目のウィンドウは、最初のウィンドウの幅に等しいオフセットで水平に開始します。

COnTheFlyWindow win[2];

win[0].Open(display, 0, 0, split_pos, h, CYGFX_DISP_LAYER_1, CYGFX_DISP_SUB_LAYER_DEFAULT,

CYGFX_DISP_FEATURE_OTF_WIN_PRIO_1, CYGFX_DISP_BLEND_SOURCE_ALPHA, 64, CYGFX_SM_FORMAT_R8G8B8A8);

win[1].Open(display, w, 0, w – split_pos, h, CYGFX_DISP_LAYER_2, CYGFX_DISP_SUB_LAYER_DEFAULT,

CYGFX_DISP_FEATURE_OTF_WIN_PRIO_2, CYGFX_DISP_BLEND_SOURCE_ALPHA, 32, CYGFX_SM_FORMAT_R8G8B8A8));

…    

 {
        render_part(ctx0, surfwin0, 0, split_pos, h );
        render_part(ctx1, surfwin1, split_pos, w - split_pos, h );

        win[0].swap();
        win[1].swap();
    }

1.1.1.2     2つの従来の(ダブルバッファ)レンダリングされたウィンドウ

OTFと同じアプローチを、2つの古典的なダブルバッファウィンドウで使用できます。 この場合、両方のウィンドウサーフェスに同じctxを使用することをお勧めします。 レンダリング後、両方のウィンドウを同じブリット同期オブジェクトと同期することをお勧めします。

COnTheFlyWindow win[2];

win[0].Open(display, 0, 0, split_pos, h, CYGFX_DISP_LAYER_1, CYGFX_DISP_SUB_LAYER_DEFAULT,

CYGFX_DISP_FEATURE_OTF_WIN_PRIO_1, CYGFX_DISP_BLEND_SOURCE_ALPHA, 64, CYGFX_SM_FORMAT_R8G8B8A8);

win[1].Open(display, w, 0, w – split_pos, h, CYGFX_DISP_LAYER_2, CYGFX_DISP_SUB_LAYER_DEFAULT,

CYGFX_DISP_FEATURE_OTF_WIN_PRIO_2, CYGFX_DISP_BLEND_SOURCE_ALPHA, 32, CYGFX_SM_FORMAT_R8G8B8A8));

{        render_part(ctx, surfwin0, 0, split_pos, h );
        render_part(ctx, surfwin1, split_pos, w - split_pos, h );
        CyGfx_BeGetSync(ctx, &sync);
        CyGfx_WinWaitSync(win[0], &sync);
        CyGfx_WinWaitSync(win[1], &sync);
        Win[0].Swap();
        Win[1].Swap();
    }

 1.1.1.3     サポートされている整列アドレスで分割された1つの従来の(ダブルバッファ)レンダリングされたウィンドウ

大きな水平解像度をレンダリングするために使用できるウィンドウは1つだけです。 この方法では、大きなバッファがレンダリングのために小さなバッファに分割されます。 これらのバッファには大きなピクセルストライドがありますが、問題は発生しません。 この方法は、必要なコンテキストが1つだけであり、追加の同期を回避できるため、この方法をお勧めします。 この方法は、ソフトウェアを少し変更するだけでハードウェアリソースの使用を減らし、上記の2つの方法に比べて有利になります。

  1. ターゲットをレンダリングするために、フルサイズと2つのサーフェス(ダブルバッファ用)を備えたウィンドウを作成:

CSurfaceWindow<2> win;
win.Open(display);
win.CreateBuffer();

  1. レンダリングループで、左右のターゲットのサーフェスプロパティを変更し、次のようにレンダリング:

左のターゲット:

CyGfx_SmSetAttribute(win.m_surface, CYGFX_SM_ATTR_WIDTH, split_pos);
render_part(ctx, win.m_surface, 0, split_pos, h );

右のターゲット:

CyGfx_SmSetAttribute(win.m_surface, CYGFX_SM_ATTR_PHYS_ADDRESS, addr + (split_pos * bpp / 8));
CyGfx_SmSetAttribute(win.m_surface, CYGFX_SM_ATTR_WIDTH, w - split_pos);
render_part(ctx, win.m_surface, split_pos, w - split_pos, h );

       3. ウィンドウに割り当てる前に、サーフェスのアドレスと幅のプロパティを元の値にリセットします。 同期関数を使用して、バッファを交換する前にレンダリングの完了を待ちます。

CyGfx_SmSetAttribute(win.m_surface, CYGFX_SM_ATTR_PHYS_ADDRESS, addr);
CyGfx_SmSetAttribute(win.m_surface, CYGFX_SM_ATTR_WIDTH, w);
CyGfx_BeGetSync(ctx, &sync);
CyGfx_WinWaitSync(win, &sync);
win.Swap();

1.1.1.4    非整列アドレスで分割された1つの従来の(ダブルバッファ)レンダリングされたウィンドウ

この方法は以前の方法と似ていますが、整列されていないアドレスに若干の変更が加えられています。 分割位置がすでに定義されていて、ピクセルあたりのターゲットビット(bpp)が次の値(1、2、4、または18)のいずれかである場合、(split_pos * bpp / 8)の値は常に整数であるとは限りません。 その場合、アドレスはバイトアラインされている必要があるため、2番目のレンダーターゲットアドレスを設定することはできません。

split_posを最大3ピクセル左または右に移動してアドレスをバイト整列にすることにより、このシナリオを回避することをお勧めします。 次に、前の方法(セクション1.1.1.3)で説明したようにレンダリングを実行できます。

このシナリオを回避できない場合は、いくつかの特別なコマンドを使用してレンダリングループを拡張し、完璧な結果を得ることができます。 左側の部分は、前のセクションのようにレンダリングできます。 ただし、適切な部分については、整列されたアドレスを見つける必要があります:

int unaligned = (bpp * split_pos) % 8;
int overlap = 0;
while (unaligned != 0
{
    overlap++;
    unaligned = (bpp * (split_pos - overlap)) % 8;
}

CopySufaceAttributes(target, win.m_surface);
CyGfx_SmSetAttribute(target, CYGFX_SM_ATTR_VIRT_ADDRESS, addr + (((offs - overlap) * bpp / 8)));
CyGfx_SmSetAttribute(target, CYGFX_SM_ATTR_WIDTH, wp + overlap);

これは、ターゲットバッファが左側で「オーバーラップ」ピクセルだけ増加することを意味します。 これらのピクセルのレンダリングを回避するには、この2番目のレンダリングループを拡張する必要があります。 ブリット操作の場合、ストアのアクティブエリアを以下のように定義することで実現できます。 アクティブエリアは、塗りつぶし操作に影響を与えません。

CyGfx_BeBindSurface(ctx, CYGFX_BE_TARGET_STORE | CYGFX_BE_TARGET_DST, target));

if (overlap != 0)

{
CyGfx_BeActiveArea(ctx, CYGFX_BE_TARGET_STORE, overlap, 0, wp + overlap, h);
CyGfx_BeSelectArea(ctx, CYGFX_BE_TARGET_SRC | CYGFX_BE_TARGET_STORE);
CyGfx_BeSetSurfAttribute(ctx, CYGFX_BE_TARGET_STORE, CYGFX_BE_SURF_ATTR_USE_CLIPPING, CYGFX_TRUE);
}

CyGfx_BeFill(ctx, overlap, 0, wp + overlap, h);
for (i = 0; i < objects; i++)
{
CyGfx_BeBindSurface(ctx, CYGFX_BE_TARGET_SRC, object[i].surf);
CyGfx_BeBlt(ctx, object[i].x - split_pos + overlap, object[i].y);
}
CyGfx_BeSelectArea(ctx, CYGFX_BE_TARGET_SRC );

1.1.2    重複するバッファを使用したレンダリング

広い領域で2つのバッファを水平方向にオーバーラップさせることにより、リストされた手順を使用することもできます。

この方法は、レンダリングオブジェクトが通常左側または右側に固定されているが、いくつかの(小さな)オブジェクトが両側にある場合に役立ちます(たとえば、回転する針が左から右に交差する場合)。 これらのオブジェクトを左側または右側のバッファで完全にレンダリングできるように、2つのバッファは範囲内でオーバーラップする必要があります。

MohammedA_41_2-1649241483421.png

 

アプリケーションでは、必要となるレンダリングオブジェクトのみをトリガーする必要があります。 CPUとGPUの時間を節約します。

欠点は、レンダリング順序を遵守する必要があることです。 たとえば、背景画像は常に最初のレンダリング呼び出しでレンダリングする必要があります。または、2ウィンドウアプローチの背景ウィンドウである必要があります。

1.1.3   制限

レンダーループを2回呼び出すと、次の制限があります。 以下を引き起こします:

  • 追加のCPU負荷(追加のレンダリング呼び出し)
  • いくつかの追加のGPU負荷(要約すると、より多くのオブジェクトがレンダリングされます)
  • 圧縮画像の追加のGPUパフォーマンス

LBOレンダリングにオブジェクト分割を使用すると、圧縮画像に必要な追加のGPUパフォーマンスを最小限に抑えることができます。 このモードではオブジェクト分割を使用し、分割位置がオブジェクト分割幅の倍になるようにオブジェクト分割幅を調整することをお勧めします。

注釈:      このKBAは、次シリーズのTRAVEO™ T2GMCUに適用されます:

  • TRAVEO™ T2G クラスター CYT3D シリーズ
  • TRAVEO™ T2G クラスター CYT4D シリーズ
0 Likes
150 Views