「App:Library:LVGL:docs:Porting:Add custom GPU」の版間の差分
(同じ利用者による、間の17版が非表示) | |||
1行目: | 1行目: | ||
https://docs.lvgl.io/8.2/porting/gpu.html | https://docs.lvgl.io/8.2/porting/gpu.html | ||
− | + | __NOTOC__ | |
== Add custom GPU == | == Add custom GPU == | ||
:{| class="wikitable" | :{| class="wikitable" | ||
14行目: | 14行目: | ||
これをフックして、GPUでレンダリングを実行したり、組み込みのソフトウェアレンダラーを完全に置き換えたりすることができます。 | これをフックして、GPUでレンダリングを実行したり、組み込みのソフトウェアレンダラーを完全に置き換えたりすることができます。 | ||
|} | |} | ||
+ | :[[App:Library:LVGL:docs:Porting#Add custom GPU|戻る : Previous]] | ||
== Draw context == | == Draw context == | ||
21行目: | 22行目: | ||
|- | |- | ||
| | | | ||
− | The core structure of drawing is <code>'''lv_draw_ctx_t'''</code>. | + | The core structure of drawing is <code style="color: #bb0000;">'''lv_draw_ctx_t'''</code>. |
It contains a pointer to a buffer where drawing should happen and a couple of callbacks to draw rectangles, texts, and other primitives. | It contains a pointer to a buffer where drawing should happen and a couple of callbacks to draw rectangles, texts, and other primitives. | ||
− | |描画のコア構造体は <code>'''lv_draw_ctx_t'''</code> です。 | + | |描画のコア構造体は <code style="color: #bb0000;">'''lv_draw_ctx_t'''</code> です。 |
これには、描画が行われるバッファへのポインタと、長方形、テキスト、およびその他のプリミティブを描画するための2つのコールバックが含まれています。 | これには、描画が行われるバッファへのポインタと、長方形、テキスト、およびその他のプリミティブを描画するための2つのコールバックが含まれています。 | ||
|} | |} | ||
+ | :[[App:Library:LVGL:docs:Porting#Add custom GPU|戻る : Previous]] | ||
=== Fields === | === Fields === | ||
34行目: | 36行目: | ||
|- | |- | ||
| | | | ||
− | <code>'''lv_draw_ctx_t'''</code> has the following fields: | + | <code style="color: #bb0000;">'''lv_draw_ctx_t'''</code> has the following fields: |
− | *<code>void * buf</code> Pointer to a buffer to draw into | + | *<code style="color: #bb0000;">void * buf</code> Pointer to a buffer to draw into |
− | * <code>lv_area_t * buf_area</code> The position and size of <code>buf</code> (absolute coordinates) | + | * <code style="color: #bb0000;">lv_area_t * buf_area</code> The position and size of <code style="color: #bb0000;">buf</code> (absolute coordinates) |
− | * <code>const lv_area_t * clip_area</code> The current clip area with absolute coordinates, always the same or smaller than <code>buf_area</code>. All drawings should be clipped to this area. | + | * <code style="color: #bb0000;">const lv_area_t * clip_area</code> The current clip area with absolute coordinates, always the same or smaller than <code style="color: #bb0000;">buf_area</code>. All drawings should be clipped to this area. |
− | *<code>void (*draw_rect)()</code> Draw a rectangle with shadow, gradient, border, etc. | + | *<code style="color: #bb0000;">void (*draw_rect)()</code> Draw a rectangle with shadow, gradient, border, etc. |
− | *<code>void (*draw_arc)()</code> Draw an arc | + | *<code style="color: #bb0000;">void (*draw_arc)()</code> Draw an arc |
− | *<code>void (*draw_img_decoded)()</code> Draw an (A)RGB image that is already decoded by LVGL. | + | *<code style="color: #bb0000;">void (*draw_img_decoded)()</code> Draw an (A)RGB image that is already decoded by LVGL. |
− | *<code>lv_res_t (*draw_img)()</code> Draw an image before decoding it (it bypasses LVGL's internal image decoders) | + | *<code style="color: #bb0000;">lv_res_t (*draw_img)()</code> Draw an image before decoding it (it bypasses LVGL's internal image decoders) |
− | *<code>void (*draw_letter)()</code> Draw a letter | + | *<code style="color: #bb0000;">void (*draw_letter)()</code> Draw a letter |
− | *<code>void (*draw_line)()</code> Draw a line | + | *<code style="color: #bb0000;">void (*draw_line)()</code> Draw a line |
− | *<code>void (*draw_polygon)()</code> Draw a polygon | + | *<code style="color: #bb0000;">void (*draw_polygon)()</code> Draw a polygon |
− | *<code>void (*draw_bg)()</code> Replace the buffer with a rect without decoration like radius or borders. | + | *<code style="color: #bb0000;">void (*draw_bg)()</code> Replace the buffer with a rect without decoration like radius or borders. |
− | *<code>void (*wait_for_finish)()</code> Wait until all background operation are finished. (E.g. GPU operations) | + | *<code style="color: #bb0000;">void (*wait_for_finish)()</code> Wait until all background operation are finished. (E.g. GPU operations) |
− | *<code>void * user_data</code> Custom user data for arbitrary purpose | + | *<code style="color: #bb0000;">void * user_data</code> Custom user data for arbitrary purpose |
(For the sake of simplicity the parameters of the callbacks are not shown here.) | (For the sake of simplicity the parameters of the callbacks are not shown here.) | ||
− | All <code>draw_*</code> callbacks receive a pointer to the current <code>draw_ctx</code> as their first parameter. | + | All <code style="color: #bb0000;">draw_*</code> callbacks receive a pointer to the current <code style="color: #bb0000;">draw_ctx</code> as their first parameter. |
− | Among the other parameters there is a descriptor that tells what to draw, e.g. for <code>draw_rect</code> it's called lv_draw_rect_dsc_t, for <code>lv_draw_line</code> it's called lv_draw_line_dsc_t, etc. | + | Among the other parameters there is a descriptor that tells what to draw, e.g. for <code style="color: #bb0000;">draw_rect</code> it's called lv_draw_rect_dsc_t, for <code style="color: #bb0000;">lv_draw_line</code> it's called lv_draw_line_dsc_t, etc. |
− | To correctly render according to a <code>draw_dsc</code> you need to be familiar with the Boxing model of LVGL and the meanings of the fields. | + | To correctly render according to a <code style="color: #bb0000;">draw_dsc</code> you need to be familiar with the Boxing model of LVGL and the meanings of the fields. |
The name and meaning of the fields are identical to name and meaning of the Style properties. | The name and meaning of the fields are identical to name and meaning of the Style properties. | ||
− | |<code>'''lv_draw_ctx_t'''</code> には次のフィールドがあります。 | + | |<code style="color: #bb0000;">'''lv_draw_ctx_t'''</code> には次のフィールドがあります。 |
− | *<code>'''void * buf'''</code> 引き込むバッファへのポインタ | + | *<code style="color: #bb0000;">'''void * buf'''</code> 引き込むバッファへのポインタ |
− | * <code>'''lv_area_t * buf_area'''</code> (絶対座標)<code>'''buf'''</code>の位置とサイズ | + | * <code style="color: #bb0000;">'''lv_area_t * buf_area'''</code> (絶対座標)<code style="color: #bb0000;">'''buf'''</code>の位置とサイズ |
− | * <code>const lv_area_t * clip_area</code> 絶対座標を持つ現在のクリップ領域、常に <code>buf_area</code> と同じか、それより小さくなります。すべての図面はこの領域にクリップする必要があります。 | + | * <code style="color: #bb0000;">const lv_area_t * clip_area</code> 絶対座標を持つ現在のクリップ領域、常に <code style="color: #bb0000;">buf_area</code> と同じか、それより小さくなります。すべての図面はこの領域にクリップする必要があります。 |
− | *<code>'''void (*draw_rect)()'''</code> 影,グラデーション,境界線などで長方形を描く。 | + | *<code style="color: #bb0000;">'''void (*draw_rect)()'''</code> 影,グラデーション,境界線などで長方形を描く。 |
− | *<code>'''void (*draw_arc)()'''</code> 円弧を描く。 | + | *<code style="color: #bb0000;">'''void (*draw_arc)()'''</code> 円弧を描く。 |
− | *<code>'''void (*draw_img_decoded)()'''</code> LVGLによってすでにデコードされている (A)RGB画像 を描画します。 | + | *<code style="color: #bb0000;">'''void (*draw_img_decoded)()'''</code> LVGLによってすでにデコードされている (A)RGB画像 を描画します。 |
− | *<code>'''lv_res_t (*draw_img)()'''</code> デコードする前に画像を描画します(LVGLの内部画像デコーダーをバイパスします) | + | *<code style="color: #bb0000;">'''lv_res_t (*draw_img)()'''</code> デコードする前に画像を描画します(LVGLの内部画像デコーダーをバイパスします) |
− | *<code>'''void (*draw_letter)()'''</code> 文字を描く | + | *<code style="color: #bb0000;">'''void (*draw_letter)()'''</code> 文字を描く |
− | *<code>'''void (*draw_line)()'''</code> 線を引く | + | *<code style="color: #bb0000;">'''void (*draw_line)()'''</code> 線を引く |
− | *<code>'''void (*draw_polygon)()'''</code> 折れ線を描く | + | *<code style="color: #bb0000;">'''void (*draw_polygon)()'''</code> 折れ線を描く |
− | *<code>'''void (*draw_bg)()'''</code> バッファを、半径や境界線などの装飾のない長方形に置き換えます。 | + | *<code style="color: #bb0000;">'''void (*draw_bg)()'''</code> バッファを、半径や境界線などの装飾のない長方形に置き換えます。 |
− | *<code>'''void (*wait_for_finish)()'''</code>すべてのバックグラウンド操作が終了するまで待ちます。(GPU操作など) | + | *<code style="color: #bb0000;">'''void (*wait_for_finish)()'''</code>すべてのバックグラウンド操作が終了するまで待ちます。(GPU操作など) |
− | *<code>'''void * user_data'''</code> 任意の目的のためのカスタムユーザーデータ | + | *<code style="color: #bb0000;">'''void * user_data'''</code> 任意の目的のためのカスタムユーザーデータ |
(簡単にするために、コールバックのパラメーターはここには示されていません。) | (簡単にするために、コールバックのパラメーターはここには示されていません。) | ||
− | すべての<code>'''draw_*'''</code>コールバックは、最初のパラメーターとして現在へのポインター<code>'''draw_ctx'''</code>を受け取ります。 | + | すべての<code style="color: #bb0000;">'''draw_*'''</code>コールバックは、最初のパラメーターとして現在へのポインター<code style="color: #bb0000;">'''draw_ctx'''</code>を受け取ります。 |
− | 他のパラメータの中には、何を描画するかを指示する記述子があります。たとえば、 <code>'''draw_rect'''</code> は '''lv_draw_rect_dsc_t''' から呼ばれて、<code>'''lv_draw_line'''</code> は '''lv_draw_line_dsc_t''' から呼ばれます。 | + | 他のパラメータの中には、何を描画するかを指示する記述子があります。たとえば、 <code style="color: #bb0000;">'''draw_rect'''</code> は '''lv_draw_rect_dsc_t''' から呼ばれて、<code style="color: #bb0000;">'''lv_draw_line'''</code> は '''lv_draw_line_dsc_t''' から呼ばれます。 |
− | <code>'''draw_dsc'''</code> に従って正しくレンダリングするには、LVGLの枠型モデルとフィールドの意味に精通している必要があります。 | + | <code style="color: #bb0000;">'''draw_dsc'''</code> に従って正しくレンダリングするには、LVGLの枠型モデルとフィールドの意味に精通している必要があります。 |
フィールドの名前と意味は、Styleプロパティの名前と同じ意味です。 | フィールドの名前と意味は、Styleプロパティの名前と同じ意味です。 | ||
|} | |} | ||
− | + | :[[App:Library:LVGL:docs:Porting#Add custom GPU|戻る : Previous]] | |
− | |||
=== Initialization === | === Initialization === | ||
95行目: | 96行目: | ||
|- | |- | ||
| | | | ||
− | The <code>lv_disp_drv_t</code> has 4 fields related to the draw context: | + | The <code style="color: #bb0000;">lv_disp_drv_t</code> has 4 fields related to the draw context: |
− | *<code>lv_draw_ctx_t * draw_ctx</code> Pointer to the <code>draw_ctx</code> of this display | + | *<code style="color: #bb0000;">lv_draw_ctx_t * draw_ctx</code> Pointer to the <code style="color: #bb0000;">draw_ctx</code> of this display |
− | * <code>'''void (*draw_ctx_init)(struct _lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx)'''</code> Callback to initialize a <code>'''draw_ctx'''</code> | + | * <code style="color: #bb0000;">'''void (*draw_ctx_init)(struct _lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx)'''</code> Callback to initialize a <code style="color: #bb0000;">'''draw_ctx'''</code> |
− | * <code>'''void (*draw_ctx_deinit)(struct _lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx)'''</code> Callback to de-initialize a <code>'''draw_ctx'''</code> | + | * <code style="color: #bb0000;">'''void (*draw_ctx_deinit)(struct _lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx)'''</code> Callback to de-initialize a <code style="color: #bb0000;">'''draw_ctx'''</code> |
− | * <code>size_t draw_ctx_size</code> Size of the draw context structure. E.g. <code>sizeof'''(lv_draw_sw_ctx_t)'''</code> | + | * <code style="color: #bb0000;">size_t draw_ctx_size</code> Size of the draw context structure. E.g. <code style="color: #bb0000;">sizeof'''(lv_draw_sw_ctx_t)'''</code> |
− | When you ignore these fields, LVGL will set default values for callbacks and size in <code>lv_disp_drv_init()</code> based on the configuration in <code>lv_conf.h</code>. | + | When you ignore these fields, LVGL will set default values for callbacks and size in <code style="color: #bb0000;">lv_disp_drv_init()</code> based on the configuration in <code style="color: #bb0000;">lv_conf.h</code>. |
− | <code>'''lv_disp_drv_register()'''</code> will allocate a <code>'''draw_ctx'''</code> based on <code>'''draw_ctx_size'''</code> and call <code>'''draw_ctx_init()'''</code> on it. | + | <code style="color: #bb0000;">'''lv_disp_drv_register()'''</code> will allocate a <code style="color: #bb0000;">'''draw_ctx'''</code> based on <code style="color: #bb0000;">'''draw_ctx_size'''</code> and call <code style="color: #bb0000;">'''draw_ctx_init()'''</code> on it. |
− | However, you can overwrite the callbacks and the size values before calling <code>'''lv_disp_drv_register()'''</code>. | + | However, you can overwrite the callbacks and the size values before calling <code style="color: #bb0000;">'''lv_disp_drv_register()'''</code>. |
− | It makes it possible to use your own <code>'''draw_ctx'''</code> with your own callbacks. | + | It makes it possible to use your own <code style="color: #bb0000;">'''draw_ctx'''</code> with your own callbacks. |
− | |<code>lv_disp_drv_t</code> には、描画コンテキストに関連する4つのフィールドがあります。 | + | |<code style="color: #bb0000;">lv_disp_drv_t</code> には、描画コンテキストに関連する4つのフィールドがあります。 |
− | *<code>lv_draw_ctx_t * draw_ctx</code> : このディスプレイの <code>'''draw_ctx'''</code> へのポインタ | + | *<code style="color: #bb0000;">lv_draw_ctx_t * draw_ctx</code> : このディスプレイの <code style="color: #bb0000;">'''draw_ctx'''</code> へのポインタ |
− | * <code>'''void (*draw_ctx_init)(struct _lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx)'''</code> : <code>draw_ctx</code> を初期化するためのコールバック | + | * <code style="color: #bb0000;">'''void (*draw_ctx_init)(struct _lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx)'''</code> : <code style="color: #bb0000;">draw_ctx</code> を初期化するためのコールバック |
− | * <code>'''void (*draw_ctx_deinit)(struct _lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx)'''</code> : <code>'''draw_ctx'''</code>の初期化を解除するためのコールバック | + | * <code style="color: #bb0000;">'''void (*draw_ctx_deinit)(struct _lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx)'''</code> : <code style="color: #bb0000;">'''draw_ctx'''</code>の初期化を解除するためのコールバック |
− | * <code>'''size_t draw_ctx_size'''</code> : 描画コンテキスト構造のサイズ。例えば<code>'''sizeof(lv_draw_sw_ctx_t)'''</code> | + | * <code style="color: #bb0000;">'''size_t draw_ctx_size'''</code> : 描画コンテキスト構造のサイズ。例えば<code style="color: #bb0000;">'''sizeof(lv_draw_sw_ctx_t)'''</code> |
− | これらのフィールドを無視した場合、LVGLは <code>'''lv_conf.h'''</code> の configuration に基づき <code>'''lv_disp_drv_init()'''</code> にコールバックとサイズのデフォルト値を設定します。 | + | これらのフィールドを無視した場合、LVGLは <code style="color: #bb0000;">'''lv_conf.h'''</code> の configuration に基づき <code style="color: #bb0000;">'''lv_disp_drv_init()'''</code> にコールバックとサイズのデフォルト値を設定します。 |
− | <code>'''lv_disp_drv_register()'''</code>は <code>'''draw_ctx_size'''</code> に基づいて <code>'''draw_ctx'''</code> を割り当て、その上で <code>'''draw_ctx_init()'''</code> を呼び出します。 | + | <code style="color: #bb0000;">'''lv_disp_drv_register()'''</code>は <code style="color: #bb0000;">'''draw_ctx_size'''</code> に基づいて <code style="color: #bb0000;">'''draw_ctx'''</code> を割り当て、その上で <code style="color: #bb0000;">'''draw_ctx_init()'''</code> を呼び出します。 |
− | ただし、を呼び出す前に、コールバックとサイズの値を上書きできます<code>'''lv_disp_drv_register()'''</code>。 | + | ただし、を呼び出す前に、コールバックとサイズの値を上書きできます<code style="color: #bb0000;">'''lv_disp_drv_register()'''</code>。 |
− | それはあなた自身のコールバックで、あなた自身である <code>'''draw_ctx'''</code> を使うことを可能にします。 | + | それはあなた自身のコールバックで、あなた自身である <code style="color: #bb0000;">'''draw_ctx'''</code> を使うことを可能にします。 |
|} | |} | ||
+ | :[[App:Library:LVGL:docs:Porting#Add custom GPU|戻る : Previous]] | ||
== Software renderer == | == Software renderer == | ||
133行目: | 135行目: | ||
|- | |- | ||
| | | | ||
− | LVGL's built in software renderer extends the basic <code>lv_draw_ctx_t</code> structure and sets the draw callbacks. It looks like this: | + | LVGL's built in software renderer extends the basic <code style="color: #bb0000;">lv_draw_ctx_t</code> structure and sets the draw callbacks. It looks like this: |
+ | <syntaxhighlight lang="C++" style="border: 1px dashed gray;"> | ||
typedef struct { | typedef struct { | ||
/** Include the basic draw_ctx type*/ | /** Include the basic draw_ctx type*/ | ||
141行目: | 144行目: | ||
void (*blend)(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc); | void (*blend)(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc); | ||
} lv_draw_sw_ctx_t; | } lv_draw_sw_ctx_t; | ||
− | Set the draw callbacks in <code>draw_ctx_init()</code> like: | + | </syntaxhighlight> |
+ | Set the draw callbacks in <code style="color: #bb0000;">draw_ctx_init()</code> like: | ||
+ | <syntaxhighlight lang="C++" style="border: 1px dashed gray;"> | ||
draw_sw_ctx->base_draw.draw_rect = lv_draw_sw_rect; | draw_sw_ctx->base_draw.draw_rect = lv_draw_sw_rect; | ||
draw_sw_ctx->base_draw.draw_letter = lv_draw_sw_letter; | draw_sw_ctx->base_draw.draw_letter = lv_draw_sw_letter; | ||
... | ... | ||
+ | </syntaxhighlight> | ||
| | | | ||
− | + | LVGLに組み込まれているソフトウェアレンダラーは、基本の構造体<code style="color: #bb0000;">lv_draw_ctx_t</code>を拡張し、描画コールバックを設定します。次のようになります。 | |
− | typedef struct { | + | <syntaxhighlight lang="C++" style="border: 1px dashed gray;"> |
+ | '''typedef struct { | ||
/**基本的なdraw_ctxタイプを含めます*/ | /**基本的なdraw_ctxタイプを含めます*/ | ||
lv_draw_ctx_t base_draw; | lv_draw_ctx_t base_draw; | ||
155行目: | 162行目: | ||
/**色または画像を領域にブレンドします*/ | /**色または画像を領域にブレンドします*/ | ||
void(* blend)(lv_draw_ctx_t * draw_ctx、const lv_draw_sw_blend_dsc_t * dsc); | void(* blend)(lv_draw_ctx_t * draw_ctx、const lv_draw_sw_blend_dsc_t * dsc); | ||
− | } lv_draw_sw_ctx_t; | + | } lv_draw_sw_ctx_t;''' |
− | <code>draw_ctx_init()</code> | + | </syntaxhighlight> |
− | draw_sw_ctx-> base_draw.draw_rect = lv_draw_sw_rect; | + | <code style="color: #bb0000;">'''draw_ctx_init()'''</code>の中では次のよう に描画コールバックを設定します。 |
+ | <syntaxhighlight lang="C++" style="border: 1px dashed gray;"> | ||
+ | '''draw_sw_ctx-> base_draw.draw_rect = lv_draw_sw_rect; | ||
draw_sw_ctx-> base_draw.draw_letter = lv_draw_sw_letter; | draw_sw_ctx-> base_draw.draw_letter = lv_draw_sw_letter; | ||
− | ... | + | ...''' |
+ | </syntaxhighlight> | ||
|} | |} | ||
+ | :[[App:Library:LVGL:docs:Porting#Add custom GPU|戻る : Previous]] | ||
=== Blend callback === | === Blend callback === | ||
168行目: | 179行目: | ||
|- | |- | ||
| | | | ||
− | As you saw above the software renderer adds the <code>blend</code> callback field. It's a special callback related to how the software renderer works. All draw operations end up in the <code>blend</code> callback which can either fill an area or copy an image to an area by considering an optional mask. | + | As you saw above the software renderer adds the <code style="color: #bb0000;">blend</code> callback field. It's a special callback related to how the software renderer works. All draw operations end up in the <code style="color: #bb0000;">blend</code> callback which can either fill an area or copy an image to an area by considering an optional mask. |
− | The <code>lv_draw_sw_blend_dsc_t</code> parameter describes what and how to blend. It has the following fields: | + | The <code style="color: #bb0000;">lv_draw_sw_blend_dsc_t</code> parameter describes what and how to blend. It has the following fields: |
− | * <code>const lv_area_t * blend_area</code> The area with absolute coordinates to draw on <code>draw_ctx->buf</code>. If <code>src_buf</code> is set, it's the coordinates of the image to blend. | + | * <code style="color: #bb0000;">const lv_area_t * blend_area</code> The area with absolute coordinates to draw on <code style="color: #bb0000;">draw_ctx->buf</code>. If <code style="color: #bb0000;">src_buf</code> is set, it's the coordinates of the image to blend. |
− | * <code>const lv_color_t * src_buf</code> Pointer to an image to blend. If set, <code>color</code> is ignored. If not set fill <code>blend_area</code> with <code>color</code> | + | * <code style="color: #bb0000;">const lv_color_t * src_buf</code> Pointer to an image to blend. If set, <code style="color: #bb0000;">color</code> is ignored. If not set fill <code style="color: #bb0000;">blend_area</code> with <code style="color: #bb0000;">color</code> |
− | * <code>lv_color_t color</code> Fill color. Used only if <code>src_buf == NULL</code> | + | * <code style="color: #bb0000;">lv_color_t color</code> Fill color. Used only if <code style="color: #bb0000;">src_buf == NULL</code> |
− | * <code>lv_opa_t * mask_buf</code> NULL if ignored, or an alpha mask to apply on <code>blend_area</code> | + | * <code style="color: #bb0000;">lv_opa_t * mask_buf</code> NULL if ignored, or an alpha mask to apply on <code style="color: #bb0000;">blend_area</code> |
− | * <code>lv_draw_mask_res_t mask_res</code> The result of the previous mask operation. (<code>LV_DRAW_MASK_RES_...</code>) | + | * <code style="color: #bb0000;">lv_draw_mask_res_t mask_res</code> The result of the previous mask operation. (<code style="color: #bb0000;">LV_DRAW_MASK_RES_...</code>) |
− | * <code>const lv_area_t * mask_area</code> The area of <code>mask_buf</code> with absolute coordinates | + | * <code style="color: #bb0000;">const lv_area_t * mask_area</code> The area of <code style="color: #bb0000;">mask_buf</code> with absolute coordinates |
− | * <code>lv_opa_t opa</code> The overall opacity | + | * <code style="color: #bb0000;">lv_opa_t opa</code> The overall opacity |
− | * <code>lv_blend_mode_t blend_mode</code> E.g. <code>LV_BLEND_MODE_ADDITIVE</code> | + | * <code style="color: #bb0000;">lv_blend_mode_t blend_mode</code> E.g. <code style="color: #bb0000;">LV_BLEND_MODE_ADDITIVE</code> |
− | |上で見たように、ソフトウェアレンダラーは<code>blend</code>コールバックフィールドを追加します。これは、ソフトウェアレンダラーの動作に関連する特別なコールバックです。すべての描画操作は<code>blend</code>コールバックで終了します。コールバックは、オプションのマスクを考慮して、領域を塗りつぶすか、画像を領域にコピーすることができます。 | + | |上で見たように、ソフトウェアレンダラーは<code style="color: #bb0000;">blend</code>コールバックフィールドを追加します。これは、ソフトウェアレンダラーの動作に関連する特別なコールバックです。すべての描画操作は<code style="color: #bb0000;">blend</code>コールバックで終了します。コールバックは、オプションのマスクを考慮して、領域を塗りつぶすか、画像を領域にコピーすることができます。 |
− | この<code>lv_draw_sw_blend_dsc_t</code> | + | この パラメータ<code style="color: #bb0000;">lv_draw_sw_blend_dsc_t</code>は、何をどのようにブレンドするかを記述します。次のフィールドがあります。 |
− | * <code>const lv_area_t * blend_area</code> | + | *<code style="color: #bb0000;">const lv_area_t * blend_area</code> :<code style="color: #bb0000;">draw_ctx->buf</code>を描画する絶対座標を持つ領域 。<code style="color: #bb0000;">src_buf</code>が設定されている場合、ブレンドする画像の座標です。 |
− | * <code>const lv_color_t * src_buf</code> | + | * <code style="color: #bb0000;">const lv_color_t * src_buf</code> ブレンドする画像へのポインタ。設定されている場合、<code style="color: #bb0000;">color</code>は無視されます。設定されていない場合、<code style="color: #bb0000;">color</code>で<code style="color: #bb0000;">blend_area</code>を塗りつぶします。 |
− | * <code>lv_color_t color</code> | + | * <code style="color: #bb0000;">lv_color_t color</code> 塗りつぶしの色。<code style="color: #bb0000;">src_buf == NULL</code>の場合にのみ使用されます |
− | * <code>lv_opa_t * mask_buf</code> | + | * <code style="color: #bb0000;">lv_opa_t * mask_buf</code> 無視された場合はNULL、または<code style="color: #bb0000;">blend_area</code>に適用するアルファマスク |
− | * <code>lv_draw_mask_res_t mask_res</code>前のマスク操作の結果。(<code>LV_DRAW_MASK_RES_...</code>) | + | * <code style="color: #bb0000;">lv_draw_mask_res_t mask_res</code> 前のマスク操作の結果。( <code style="color: #bb0000;">LV_DRAW_MASK_RES_...</code> ) |
− | * <code>const lv_area_t * mask_area</code> | + | * <code style="color: #bb0000;">const lv_area_t * mask_area</code> :<code style="color: #bb0000;">mask_buf</code> 絶対座標のある領域 |
− | * <code>lv_opa_t opa</code>全体的な不透明度 | + | * <code style="color: #bb0000;">lv_opa_t opa</code> 全体的な不透明度 |
− | * <code>lv_blend_mode_t blend_mode</code>例えば<code>LV_BLEND_MODE_ADDITIVE</code> | + | * <code style="color: #bb0000;">lv_blend_mode_t blend_mode</code> 例えば <code style="color: #bb0000;">LV_BLEND_MODE_ADDITIVE</code> |
|} | |} | ||
+ | :[[App:Library:LVGL:docs:Porting#Add custom GPU|戻る : Previous]] | ||
== Extend the software renderer == | == Extend the software renderer == | ||
204行目: | 216行目: | ||
Let's take a practical example: you would like to use your MCUs GPU for color fill operations only. | Let's take a practical example: you would like to use your MCUs GPU for color fill operations only. | ||
− | As all draw callbacks call <code>blend</code> callback to fill an area in the end only the <code>blend</code> callback needs to be overwritten. | + | As all draw callbacks call <code style="color: #bb0000;">blend</code> callback to fill an area in the end only the <code style="color: #bb0000;">blend</code> callback needs to be overwritten. |
− | First extend <code>lv_draw_sw_ctx_t</code>: | + | First extend <code style="color: #bb0000;">lv_draw_sw_ctx_t</code>: |
− | + | <syntaxhighlight lang="C++" style="border: 1px dashed gray;"> | |
/*We don't add new fields, so just for clarity add new type*/ | /*We don't add new fields, so just for clarity add new type*/ | ||
typedef lv_draw_sw_ctx_t my_draw_ctx_t; | typedef lv_draw_sw_ctx_t my_draw_ctx_t; | ||
222行目: | 234行目: | ||
my_draw_ctx->base_draw.wait_for_finish = my_gpu_wait; | my_draw_ctx->base_draw.wait_for_finish = my_gpu_wait; | ||
} | } | ||
− | After calling <code>lv_disp_draw_init(&drv)</code> you can assign the new <code>draw_ctx_init</code> callback and set <code>draw_ctx_size</code> to overwrite the defaults: | + | </syntaxhighlight> |
+ | |||
+ | |||
+ | After calling <code style="color: #bb0000;">lv_disp_draw_init(&drv)</code> you can assign the new <code style="color: #bb0000;">draw_ctx_init</code> callback and set <code style="color: #bb0000;">draw_ctx_size</code> to overwrite the defaults: | ||
+ | <syntaxhighlight lang="C++" style="border: 1px dashed gray;"> | ||
static lv_disp_drv_t drv; | static lv_disp_drv_t drv; | ||
lv_disp_draw_init(&drv); | lv_disp_draw_init(&drv); | ||
234行目: | 250行目: | ||
lv_disp_drv_register(&drv); | lv_disp_drv_register(&drv); | ||
− | This way when LVGL calls <code>blend</code> it will call <code>my_draw_blend</code> and we can do custom GPU operations. Here is a complete example: | + | </syntaxhighlight> |
+ | |||
+ | |||
+ | This way when LVGL calls <code style="color: #bb0000;">blend</code> it will call <code style="color: #bb0000;">my_draw_blend</code> and we can do custom GPU operations. | ||
+ | |||
+ | Here is a complete example: | ||
+ | <syntaxhighlight lang="C++" style="border: 1px dashed gray;"> | ||
void my_draw_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc) | void my_draw_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc) | ||
{ | { | ||
261行目: | 283行目: | ||
} | } | ||
} | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
The implementation of wait callback is much simpler: | The implementation of wait callback is much simpler: | ||
+ | <syntaxhighlight lang="C++" style="border: 1px dashed gray;"> | ||
void my_gpu_wait(lv_draw_ctx_t * draw_ctx) | void my_gpu_wait(lv_draw_ctx_t * draw_ctx) | ||
{ | { | ||
269行目: | 295行目: | ||
lv_draw_sw_wait_for_finish(draw_ctx); | lv_draw_sw_wait_for_finish(draw_ctx); | ||
} | } | ||
+ | </syntaxhighlight> | ||
| | | | ||
+ | 実際の例を見てみましょう。MCUGPUをカラーフィル操作にのみ使用したいとします。 | ||
− | + | すべての描画コールバックはコールバック<code style="color: #bb0000;">blend</code>を呼び出して最終的に領域を埋めるため、<code style="color: #bb0000;">blend</code>コールバックのみを上書きする必要があります。 | |
− | |||
− | |||
− | 最初の拡張<code>lv_draw_sw_ctx_t</code>: | + | 最初の拡張<code style="color: #bb0000;">lv_draw_sw_ctx_t</code>: |
+ | <syntaxhighlight lang="C++" style="border: 1px dashed gray;"> | ||
/ *新しいフィールドは追加しないため、わかりやすくするために新しいタイプを追加します* / | / *新しいフィールドは追加しないため、わかりやすくするために新しいタイプを追加します* / | ||
typedef lv_draw_sw_ctx_t my_draw_ctx_t; | typedef lv_draw_sw_ctx_t my_draw_ctx_t; | ||
291行目: | 318行目: | ||
my_draw_ctx-> base_draw.wait_for_finish = my_gpu_wait; | my_draw_ctx-> base_draw.wait_for_finish = my_gpu_wait; | ||
} | } | ||
− | + | </syntaxhighlight> | |
+ | <code style="color: #bb0000;">lv_disp_draw_init(&drv)</code>を呼び出した後、新しいコールバック<code style="color: #bb0000;">draw_ctx_initdraw_ctx_size</code>を割り当て、デフォルトを上書きするように 設定できます。 | ||
+ | <syntaxhighlight lang="C++" style="border: 1px dashed gray;"> | ||
static lv_disp_drv_t drv; | static lv_disp_drv_t drv; | ||
lv_disp_draw_init(&drv); | lv_disp_draw_init(&drv); | ||
303行目: | 332行目: | ||
lv_disp_drv_register(&drv); | lv_disp_drv_register(&drv); | ||
− | このようにして、LVGLが<code>blend</code> | + | </syntaxhighlight> |
+ | |||
+ | |||
+ | このようにして、LVGLが<code style="color: #bb0000;">blend</code>呼び出すと、<code style="color: #bb0000;">my_draw_blend</code>が呼び出され、カスタムGPU操作を実行できます。 | ||
+ | |||
+ | 完全な例を次に示します。 | ||
+ | <syntaxhighlight lang="C++" style="border: 1px dashed gray;"> | ||
void my_draw_blend(lv_draw_ctx_t * draw_ctx、const lv_draw_sw_blend_dsc_t * dsc) | void my_draw_blend(lv_draw_ctx_t * draw_ctx、const lv_draw_sw_blend_dsc_t * dsc) | ||
{ | { | ||
330行目: | 365行目: | ||
} | } | ||
} | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
待機コールバックの実装ははるかに簡単です。 | 待機コールバックの実装ははるかに簡単です。 | ||
+ | <syntaxhighlight lang="C++" style="border: 1px dashed gray;"> | ||
void my_gpu_wait(lv_draw_ctx_t * draw_ctx) | void my_gpu_wait(lv_draw_ctx_t * draw_ctx) | ||
{ | { | ||
338行目: | 377行目: | ||
lv_draw_sw_wait_for_finish(draw_ctx); | lv_draw_sw_wait_for_finish(draw_ctx); | ||
} | } | ||
+ | </syntaxhighlight> | ||
|} | |} | ||
+ | :[[App:Library:LVGL:docs:Porting#Add custom GPU|戻る : Previous]] | ||
=== New rectangle drawer === | === New rectangle drawer === | ||
346行目: | 387行目: | ||
|- | |- | ||
| | | | ||
− | If your MCU has a more powerful GPU that can draw e.g. rounded rectangles you can replace the original software drawer too. A custom <code>draw_rect</code> callback might look like this: | + | If your MCU has a more powerful GPU that can draw e.g. rounded rectangles you can replace the original software drawer too. A custom <code style="color: #bb0000;">draw_rect</code> callback might look like this: |
+ | <syntaxhighlight lang="C++" style="border: 1px dashed gray;"> | ||
void my_draw_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords) | void my_draw_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords) | ||
{ | { | ||
370行目: | 412行目: | ||
} | } | ||
} | } | ||
− | <code>my_draw_rect</code> can fully bypass the use of <code>blend</code> callback if needed. | + | </syntaxhighlight> |
− | |MCUに丸みを帯びた長方形などを描画できるより強力なGPUがある場合は、元のソフトウェアドロワーを置き換えることもできます。カスタム<code>draw_rect</code>コールバックは次のようになります。 | + | <code style="color: #bb0000;">my_draw_rect</code> can fully bypass the use of <code style="color: #bb0000;">blend</code> callback if needed. |
+ | |MCUに丸みを帯びた長方形などを描画できるより強力なGPUがある場合は、元のソフトウェアドロワーを置き換えることもできます。カスタム<code style="color: #bb0000;">draw_rect</code>コールバックは次のようになります。 | ||
+ | <syntaxhighlight lang="C++" style="border: 1px dashed gray;"> | ||
void my_draw_rect(lv_draw_ctx_t * draw_ctx、const lv_draw_rect_dsc_t * dsc、const lv_area_t * coords) | void my_draw_rect(lv_draw_ctx_t * draw_ctx、const lv_draw_rect_dsc_t * dsc、const lv_area_t * coords) | ||
{ | { | ||
395行目: | 439行目: | ||
} | } | ||
} | } | ||
− | <code>my_draw_rectblend</code> | + | </syntaxhighlight> |
+ | 必要に応じて、<code style="color: #bb0000;">my_draw_rectblend</code>は<code style="color: #bb0000;">blend</code> コールバック の使用を完全にバイパスできます。 | ||
|} | |} | ||
+ | :[[App:Library:LVGL:docs:Porting#Add custom GPU|戻る : Previous]] | ||
== Fully custom draw engine == | == Fully custom draw engine == | ||
404行目: | 450行目: | ||
|- | |- | ||
| | | | ||
− | For example if your MCU/MPU supports a powerful vector graphics engine you might use only that instead of LVGL's SW renderer. In this case, you need to base the renderer on the basic <code>lv_draw_ctx_t</code> (instead of <code>lv_draw_sw_ctx_t</code>) and extend/initialize it as you wish. | + | For example if your MCU/MPU supports a powerful vector graphics engine you might use only that instead of LVGL's SW renderer. |
− | |たとえば、MCU / MCUが強力なベクターグラフィックエンジンをサポートしている場合は、LVGLのSWレンダラーの代わりにそれだけを使用できます。<code> | + | |
+ | |||
+ | In this case, you need to base the renderer on the basic <code style="color: #bb0000;">lv_draw_ctx_t</code> (instead of <code style="color: #bb0000;">lv_draw_sw_ctx_t</code>) and extend/initialize it as you wish. | ||
+ | |たとえば、MCU / MCUが強力なベクターグラフィックエンジンをサポートしている場合は、LVGLのSWレンダラーの代わりにそれだけを使用できます。 | ||
+ | |||
+ | |||
+ | この場合、基本に基づいて、(<code style="color: #bb0000;">lv_draw_sw_ctx_t</code>ではなく)<code style="color: #bb0000;">lv_draw_ctx_t</code>レンダラーを必要に応じて拡張/初期化する必要があります。 | ||
|} | |} | ||
− | + | :[[App:Library:LVGL:docs:Porting#Add custom GPU|戻る : Previous]] | |
− | |||
− | [[App:Library:LVGL:docs:Porting|戻る : Previous]] |
2022年8月18日 (木) 22:46時点における最新版
https://docs.lvgl.io/8.2/porting/gpu.html
Add custom GPU
英文 自動翻訳 LVGL has a flexible and extendable draw pipeline.
You can hook it to do some rendering with a GPU or even completely replace the built-in software renderer.
LVGLには、柔軟で拡張可能な描画パイプラインがあります。 これをフックして、GPUでレンダリングを実行したり、組み込みのソフトウェアレンダラーを完全に置き換えたりすることができます。
Draw context
英文 自動翻訳 The core structure of drawing is
lv_draw_ctx_t
.It contains a pointer to a buffer where drawing should happen and a couple of callbacks to draw rectangles, texts, and other primitives.
描画のコア構造体は lv_draw_ctx_t
です。これには、描画が行われるバッファへのポインタと、長方形、テキスト、およびその他のプリミティブを描画するための2つのコールバックが含まれています。
Fields
英文 自動翻訳 lv_draw_ctx_t
has the following fields:void * buf
Pointer to a buffer to draw intolv_area_t * buf_area
The position and size ofbuf
(absolute coordinates)const lv_area_t * clip_area
The current clip area with absolute coordinates, always the same or smaller thanbuf_area
. All drawings should be clipped to this area.void (*draw_rect)()
Draw a rectangle with shadow, gradient, border, etc.void (*draw_arc)()
Draw an arcvoid (*draw_img_decoded)()
Draw an (A)RGB image that is already decoded by LVGL.lv_res_t (*draw_img)()
Draw an image before decoding it (it bypasses LVGL's internal image decoders)void (*draw_letter)()
Draw a lettervoid (*draw_line)()
Draw a linevoid (*draw_polygon)()
Draw a polygonvoid (*draw_bg)()
Replace the buffer with a rect without decoration like radius or borders.void (*wait_for_finish)()
Wait until all background operation are finished. (E.g. GPU operations)void * user_data
Custom user data for arbitrary purpose
(For the sake of simplicity the parameters of the callbacks are not shown here.)
All
draw_*
callbacks receive a pointer to the currentdraw_ctx
as their first parameter.Among the other parameters there is a descriptor that tells what to draw, e.g. for
draw_rect
it's called lv_draw_rect_dsc_t, forlv_draw_line
it's called lv_draw_line_dsc_t, etc.To correctly render according to a
draw_dsc
you need to be familiar with the Boxing model of LVGL and the meanings of the fields.The name and meaning of the fields are identical to name and meaning of the Style properties.
lv_draw_ctx_t
には次のフィールドがあります。void * buf
引き込むバッファへのポインタlv_area_t * buf_area
(絶対座標)buf
の位置とサイズconst lv_area_t * clip_area
絶対座標を持つ現在のクリップ領域、常にbuf_area
と同じか、それより小さくなります。すべての図面はこの領域にクリップする必要があります。void (*draw_rect)()
影,グラデーション,境界線などで長方形を描く。void (*draw_arc)()
円弧を描く。void (*draw_img_decoded)()
LVGLによってすでにデコードされている (A)RGB画像 を描画します。lv_res_t (*draw_img)()
デコードする前に画像を描画します(LVGLの内部画像デコーダーをバイパスします)void (*draw_letter)()
文字を描くvoid (*draw_line)()
線を引くvoid (*draw_polygon)()
折れ線を描くvoid (*draw_bg)()
バッファを、半径や境界線などの装飾のない長方形に置き換えます。void (*wait_for_finish)()
すべてのバックグラウンド操作が終了するまで待ちます。(GPU操作など)void * user_data
任意の目的のためのカスタムユーザーデータ
(簡単にするために、コールバックのパラメーターはここには示されていません。)
すべてのdraw_*
コールバックは、最初のパラメーターとして現在へのポインターdraw_ctx
を受け取ります。他のパラメータの中には、何を描画するかを指示する記述子があります。たとえば、
draw_rect
は lv_draw_rect_dsc_t から呼ばれて、lv_draw_line
は lv_draw_line_dsc_t から呼ばれます。draw_dsc
に従って正しくレンダリングするには、LVGLの枠型モデルとフィールドの意味に精通している必要があります。フィールドの名前と意味は、Styleプロパティの名前と同じ意味です。
Initialization
英文 自動翻訳 The
lv_disp_drv_t
has 4 fields related to the draw context:lv_draw_ctx_t * draw_ctx
Pointer to thedraw_ctx
of this displayvoid (*draw_ctx_init)(struct _lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx)
Callback to initialize adraw_ctx
void (*draw_ctx_deinit)(struct _lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx)
Callback to de-initialize adraw_ctx
size_t draw_ctx_size
Size of the draw context structure. E.g.sizeof(lv_draw_sw_ctx_t)
When you ignore these fields, LVGL will set default values for callbacks and size in
lv_disp_drv_init()
based on the configuration inlv_conf.h
.
lv_disp_drv_register()
will allocate adraw_ctx
based ondraw_ctx_size
and calldraw_ctx_init()
on it.However, you can overwrite the callbacks and the size values before calling
lv_disp_drv_register()
.It makes it possible to use your own
draw_ctx
with your own callbacks.lv_disp_drv_t
には、描画コンテキストに関連する4つのフィールドがあります。lv_draw_ctx_t * draw_ctx
: このディスプレイのdraw_ctx
へのポインタvoid (*draw_ctx_init)(struct _lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx)
:draw_ctx
を初期化するためのコールバックvoid (*draw_ctx_deinit)(struct _lv_disp_drv_t * disp_drv, lv_draw_ctx_t * draw_ctx)
:draw_ctx
の初期化を解除するためのコールバックsize_t draw_ctx_size
: 描画コンテキスト構造のサイズ。例えばsizeof(lv_draw_sw_ctx_t)
これらのフィールドを無視した場合、LVGLは
lv_conf.h
の configuration に基づきlv_disp_drv_init()
にコールバックとサイズのデフォルト値を設定します。
lv_disp_drv_register()
はdraw_ctx_size
に基づいてdraw_ctx
を割り当て、その上でdraw_ctx_init()
を呼び出します。ただし、を呼び出す前に、コールバックとサイズの値を上書きできます
lv_disp_drv_register()
。それはあなた自身のコールバックで、あなた自身である
draw_ctx
を使うことを可能にします。
Software renderer
英文 自動翻訳 LVGL's built in software renderer extends the basic
lv_draw_ctx_t
structure and sets the draw callbacks. It looks like this:typedef struct { /** Include the basic draw_ctx type*/ lv_draw_ctx_t base_draw; /** Blend a color or image to an area*/ void (*blend)(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc); } lv_draw_sw_ctx_t;
Set the draw callbacks in
draw_ctx_init()
like:draw_sw_ctx->base_draw.draw_rect = lv_draw_sw_rect; draw_sw_ctx->base_draw.draw_letter = lv_draw_sw_letter; ...
LVGLに組み込まれているソフトウェアレンダラーは、基本の構造体lv_draw_ctx_t
を拡張し、描画コールバックを設定します。次のようになります。'''typedef struct { /**基本的なdraw_ctxタイプを含めます*/ lv_draw_ctx_t base_draw; /**色または画像を領域にブレンドします*/ void(* blend)(lv_draw_ctx_t * draw_ctx、const lv_draw_sw_blend_dsc_t * dsc); } lv_draw_sw_ctx_t;'''
draw_ctx_init()
の中では次のよう に描画コールバックを設定します。'''draw_sw_ctx-> base_draw.draw_rect = lv_draw_sw_rect; draw_sw_ctx-> base_draw.draw_letter = lv_draw_sw_letter; ...'''
Blend callback
英文 自動翻訳 As you saw above the software renderer adds the
blend
callback field. It's a special callback related to how the software renderer works. All draw operations end up in theblend
callback which can either fill an area or copy an image to an area by considering an optional mask.The
lv_draw_sw_blend_dsc_t
parameter describes what and how to blend. It has the following fields:const lv_area_t * blend_area
The area with absolute coordinates to draw ondraw_ctx->buf
. Ifsrc_buf
is set, it's the coordinates of the image to blend.const lv_color_t * src_buf
Pointer to an image to blend. If set,color
is ignored. If not set fillblend_area
withcolor
lv_color_t color
Fill color. Used only ifsrc_buf == NULL
lv_opa_t * mask_buf
NULL if ignored, or an alpha mask to apply onblend_area
lv_draw_mask_res_t mask_res
The result of the previous mask operation. (LV_DRAW_MASK_RES_...
)const lv_area_t * mask_area
The area ofmask_buf
with absolute coordinateslv_opa_t opa
The overall opacitylv_blend_mode_t blend_mode
E.g.LV_BLEND_MODE_ADDITIVE
上で見たように、ソフトウェアレンダラーは blend
コールバックフィールドを追加します。これは、ソフトウェアレンダラーの動作に関連する特別なコールバックです。すべての描画操作はblend
コールバックで終了します。コールバックは、オプションのマスクを考慮して、領域を塗りつぶすか、画像を領域にコピーすることができます。この パラメータ
lv_draw_sw_blend_dsc_t
は、何をどのようにブレンドするかを記述します。次のフィールドがあります。const lv_area_t * blend_area
:draw_ctx->buf
を描画する絶対座標を持つ領域 。src_buf
が設定されている場合、ブレンドする画像の座標です。const lv_color_t * src_buf
ブレンドする画像へのポインタ。設定されている場合、color
は無視されます。設定されていない場合、color
でblend_area
を塗りつぶします。lv_color_t color
塗りつぶしの色。src_buf == NULL
の場合にのみ使用されますlv_opa_t * mask_buf
無視された場合はNULL、またはblend_area
に適用するアルファマスクlv_draw_mask_res_t mask_res
前のマスク操作の結果。(LV_DRAW_MASK_RES_...
)const lv_area_t * mask_area
:mask_buf
絶対座標のある領域lv_opa_t opa
全体的な不透明度lv_blend_mode_t blend_mode
例えばLV_BLEND_MODE_ADDITIVE
Extend the software renderer
New blend callback
英文 自動翻訳 Let's take a practical example: you would like to use your MCUs GPU for color fill operations only.
As all draw callbacks call
blend
callback to fill an area in the end only theblend
callback needs to be overwritten.First extend
lv_draw_sw_ctx_t
:/*We don't add new fields, so just for clarity add new type*/ typedef lv_draw_sw_ctx_t my_draw_ctx_t; void my_draw_ctx_init(lv_disp_drv_t * drv, lv_draw_ctx_t * draw_ctx) { /*Initialize the parent type first */ lv_draw_sw_init_ctx(drv, draw_ctx); /*Change some callbacks*/ my_draw_ctx_t * my_draw_ctx = (my_draw_ctx_t *)draw_ctx; my_draw_ctx->blend = my_draw_blend; my_draw_ctx->base_draw.wait_for_finish = my_gpu_wait; }
After callinglv_disp_draw_init(&drv)
you can assign the newdraw_ctx_init
callback and setdraw_ctx_size
to overwrite the defaults:static lv_disp_drv_t drv; lv_disp_draw_init(&drv); drv->hor_res = my_hor_res; drv->ver_res = my_ver_res; drv->flush_cb = my_flush_cb; /*New draw ctx settings*/ drv->draw_ctx_init = my_draw_ctx_init; drv->draw_ctx_size = sizeof(my_draw_ctx_t); lv_disp_drv_register(&drv);
This way when LVGL callsblend
it will callmy_draw_blend
and we can do custom GPU operations.Here is a complete example:
void my_draw_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend_dsc_t * dsc) { /*Let's get the blend area which is the intersection of the area to fill and the clip area.*/ lv_area_t blend_area; if(!_lv_area_intersect(&blend_area, dsc->blend_area, draw_ctx->clip_area)) return; /*Fully clipped, nothing to do*/ /*Fill only non masked, fully opaque, normal blended and not too small areas*/ if(dsc->src_buf == NULL && dsc->mask == NULL && dsc->opa >= LV_OPA_MAX && dsc->blend_mode == LV_BLEND_MODE_NORMAL && lv_area_get_size(&blend_area) > 100) { /*Got the first pixel on the buffer*/ lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area); /*Width of the destination buffer*/ lv_color_t * dest_buf = draw_ctx->buf; dest_buf += dest_stride * (blend_area.y1 - draw_ctx->buf_area->y1) + (blend_area.x1 - draw_ctx->buf_area->x1); /*Make the blend area relative to the buffer*/ lv_area_move(&blend_area, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1); /*Call your custom gou fill function to fill blend_area, on dest_buf with dsc->color*/ my_gpu_fill(dest_buf, dest_stride, &blend_area, dsc->color); } /*Fallback: the GPU doesn't support these settings. Call the SW renderer.*/ else { lv_draw_sw_blend_basic(draw_ctx, dsc); } }
The implementation of wait callback is much simpler:void my_gpu_wait(lv_draw_ctx_t * draw_ctx) { while(my_gpu_is_working()); /*Call SW renderer's wait callback too*/ lv_draw_sw_wait_for_finish(draw_ctx); }
実際の例を見てみましょう。MCUGPUをカラーフィル操作にのみ使用したいとします。
すべての描画コールバックはコールバックblend
を呼び出して最終的に領域を埋めるため、blend
コールバックのみを上書きする必要があります。最初の拡張
lv_draw_sw_ctx_t
:/ *新しいフィールドは追加しないため、わかりやすくするために新しいタイプを追加します* / typedef lv_draw_sw_ctx_t my_draw_ctx_t; void my_draw_ctx_init(lv_disp_drv_t * drv、lv_draw_ctx_t * draw_ctx) { /*最初に親タイプを初期化します*/ lv_draw_sw_init_ctx(drv、draw_ctx); /*一部のコールバックを変更します*/ my_draw_ctx_t * my_draw_ctx =(my_draw_ctx_t *)draw_ctx; my_draw_ctx-> blend = my_draw_blend; my_draw_ctx-> base_draw.wait_for_finish = my_gpu_wait; }
lv_disp_draw_init(&drv)
を呼び出した後、新しいコールバックdraw_ctx_initdraw_ctx_size
を割り当て、デフォルトを上書きするように 設定できます。static lv_disp_drv_t drv; lv_disp_draw_init(&drv); drv-> hor_res = my_hor_res; drv-> ver_res = my_ver_res; drv-> flush_cb = my_flush_cb; /*新しい描画ctx設定*/ drv-> draw_ctx_init = my_draw_ctx_init; drv-> draw_ctx_size = sizeof(my_draw_ctx_t); lv_disp_drv_register(&drv);
このようにして、LVGLがblend
呼び出すと、my_draw_blend
が呼び出され、カスタムGPU操作を実行できます。完全な例を次に示します。
void my_draw_blend(lv_draw_ctx_t * draw_ctx、const lv_draw_sw_blend_dsc_t * dsc) { /*塗りつぶす領域とクリップ領域の交点であるブレンド領域を取得しましょう。*/ lv_area_t blend_area; if(!_ lv_area_intersect(&blend_area、dsc-> blend_area、draw_ctx-> clip_area))return; / *完全にクリップされ、何もしません* / / *マスクされていない、完全に不透明な、通常のブレンドで、小さすぎない領域のみを塗りつぶします* / if(dsc-> src_buf == NULL && dsc-> mask == NULL && dsc-> opa> = LV_OPA_MAX && dsc-> blend_mode == LV_BLEND_MODE_NORMAL && lv_area_get_size(&blend_area)> 100){ /*バッファの最初のピクセルを取得しました*/ lv_coord_t dest_stride = lv_area_get_width(draw_ctx-> buf_area); /*宛先バッファの幅*/ lv_color_t * dest_buf = draw_ctx-> buf; dest_buf + = dest_stride *(blend_area.y1-draw_ctx-> buf_area-> y1)+(blend_area.x1-draw_ctx-> buf_area-> x1); /*バッファを基準にしてブレンド領域を作成します*/ lv_area_move(&blend_area、-draw_ctx-> buf_area-> x1、-draw_ctx-> buf_area-> y1); /*カスタムgoufill関数を呼び出して、dest_bufのblend_areaをdsc->colorで塗りつぶします*/ my_gpu_fill(dest_buf、dest_stride、&blend_area、dsc-> color); } / *フォールバック:GPUはこれらの設定をサポートしていません。SWレンダラーを呼び出します。*/ そうしないと { lv_draw_sw_blend_basic(draw_ctx、dsc); } }
待機コールバックの実装ははるかに簡単です。void my_gpu_wait(lv_draw_ctx_t * draw_ctx) { while(my_gpu_is_working()); /*SWレンダラーの待機コールバックも呼び出します*/ lv_draw_sw_wait_for_finish(draw_ctx); }
New rectangle drawer
英文 自動翻訳 If your MCU has a more powerful GPU that can draw e.g. rounded rectangles you can replace the original software drawer too. A custom
draw_rect
callback might look like this:void my_draw_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, const lv_area_t * coords) { if(lv_draw_mask_is_any(coords) == false && dsc->grad == NULL && dsc->bg_img_src == NULL && dsc->shadow_width == 0 && dsc->blend_mode = LV_BLEND_MODE_NORMAL) { /*Draw the background*/ my_bg_drawer(draw_ctx, coords, dsc->bg_color, dsc->radius); /*Draw the border if any*/ if(dsc->border_width) { my_border_drawer(draw_ctx, coords, dsc->border_width, dsc->border_color, dsc->border_opa) } /*Draw the outline if any*/ if(dsc->outline_width) { my_outline_drawer(draw_ctx, coords, dsc->outline_width, dsc->outline_color, dsc->outline_opa, dsc->outline_pad) } } /*Fallback*/ else { lv_draw_sw_rect(draw_ctx, dsc, coords); } }
my_draw_rect
can fully bypass the use ofblend
callback if needed.MCUに丸みを帯びた長方形などを描画できるより強力なGPUがある場合は、元のソフトウェアドロワーを置き換えることもできます。カスタム draw_rect
コールバックは次のようになります。void my_draw_rect(lv_draw_ctx_t * draw_ctx、const lv_draw_rect_dsc_t * dsc、const lv_area_t * coords) { if(lv_draw_mask_is_any(coords)== false && dsc-> grad == NULL && dsc-> bg_img_src == NULL && dsc-> shadow_width == 0 && dsc-> blend_mode = LV_BLEND_MODE_NORMAL) { /*背景を描く*/ my_bg_drawer(draw_ctx、coords、dsc-> bg_color、dsc-> radius); /*境界線がある場合は描画します*/ if(dsc-> border_width){ my_border_drawer(draw_ctx、coords、dsc-> border_width、dsc-> border_color、dsc-> border_opa) } /*もしあれば輪郭を描きます*/ if(dsc-> overlay_width){ my_outline_drawer(draw_ctx、coords、dsc->outline_width、dsc->outline_color、dsc->outline_opa、dsc->outline_pad) } } /*後退する*/ そうしないと { lv_draw_sw_rect(draw_ctx、dsc、coords); } }
必要に応じて、
my_draw_rectblend
はblend
コールバック の使用を完全にバイパスできます。
Fully custom draw engine
英文 自動翻訳 For example if your MCU/MPU supports a powerful vector graphics engine you might use only that instead of LVGL's SW renderer.
In this case, you need to base the renderer on the basiclv_draw_ctx_t
(instead oflv_draw_sw_ctx_t
) and extend/initialize it as you wish.たとえば、MCU / MCUが強力なベクターグラフィックエンジンをサポートしている場合は、LVGLのSWレンダラーの代わりにそれだけを使用できます。
この場合、基本に基づいて、(lv_draw_sw_ctx_t
ではなく)lv_draw_ctx_t
レンダラーを必要に応じて拡張/初期化する必要があります。