「App:Library:LVGL:docs:Porting:Add custom GPU」の版間の差分
154行目: | 154行目: | ||
− | + | LVGLに組み込まれているソフトウェアレンダラーは、基本の構造体<code style="color: #bb0000;">lv_draw_ctx_t</code>を拡張し、描画コールバックを設定します。次のようになります。 | |
<syntaxhighlight lang="C++" style="border: 1px dashed gray;"> | <syntaxhighlight lang="C++" style="border: 1px dashed gray;"> | ||
'''typedef struct { | '''typedef struct { | ||
164行目: | 164行目: | ||
} lv_draw_sw_ctx_t;''' | } lv_draw_sw_ctx_t;''' | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | <code style="color: #bb0000;">'''draw_ctx_init()'''</code> | + | <code style="color: #bb0000;">'''draw_ctx_init()'''</code>の中では次のよう に描画コールバックを設定します。 |
<syntaxhighlight lang="C++" style="border: 1px dashed gray;"> | <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; | ||
193行目: | 193行目: | ||
|上で見たように、ソフトウェアレンダラーは<code style="color: #bb0000;">blend</code>コールバックフィールドを追加します。これは、ソフトウェアレンダラーの動作に関連する特別なコールバックです。すべての描画操作は<code style="color: #bb0000;">blend</code>コールバックで終了します。コールバックは、オプションのマスクを考慮して、領域を塗りつぶすか、画像を領域にコピーすることができます。 | |上で見たように、ソフトウェアレンダラーは<code style="color: #bb0000;">blend</code>コールバックフィールドを追加します。これは、ソフトウェアレンダラーの動作に関連する特別なコールバックです。すべての描画操作は<code style="color: #bb0000;">blend</code>コールバックで終了します。コールバックは、オプションのマスクを考慮して、領域を塗りつぶすか、画像を領域にコピーすることができます。 | ||
− | この<code style="color: #bb0000;">lv_draw_sw_blend_dsc_t</code> | + | この パラメータ<code style="color: #bb0000;">lv_draw_sw_blend_dsc_t</code>は、何をどのようにブレンドするかを記述します。次のフィールドがあります。 |
− | * <code style="color: #bb0000;">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 style="color: #bb0000;">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 style="color: #bb0000;">lv_color_t color</code> | + | * <code style="color: #bb0000;">lv_color_t color</code> 塗りつぶしの色。<code style="color: #bb0000;">src_buf == NULL</code>の場合にのみ使用されます |
− | * <code style="color: #bb0000;">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 style="color: #bb0000;">lv_draw_mask_res_t mask_res</code> 前のマスク操作の結果。( <code style="color: #bb0000;">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 style="color: #bb0000;">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 style="color: #bb0000;">lv_opa_t opa</code> 全体的な不透明度 | * <code style="color: #bb0000;">lv_opa_t opa</code> 全体的な不透明度 | ||
* <code style="color: #bb0000;">lv_blend_mode_t blend_mode</code> 例えば <code style="color: #bb0000;">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> | ||
235行目: | 235行目: | ||
} | } | ||
</syntaxhighlight> | </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: | 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;"> | <syntaxhighlight lang="C++" style="border: 1px dashed gray;"> | ||
249行目: | 251行目: | ||
lv_disp_drv_register(&drv); | lv_disp_drv_register(&drv); | ||
</syntaxhighlight> | </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: | + | |
+ | |||
+ | 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;"> | <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) | ||
278行目: | 284行目: | ||
} | } | ||
</syntaxhighlight> | </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;"> | <syntaxhighlight lang="C++" style="border: 1px dashed gray;"> | ||
291行目: | 299行目: | ||
実際の例を見てみましょう。MCUGPUをカラーフィル操作にのみ使用したいとします。 | 実際の例を見てみましょう。MCUGPUをカラーフィル操作にのみ使用したいとします。 | ||
− | + | ||
+ | すべての描画コールバックはコールバック<code style="color: #bb0000;">blend</code>を呼び出して最終的に領域を埋めるため、<code style="color: #bb0000;">blend</code>コールバックのみを上書きする必要があります。 | ||
最初の拡張<code style="color: #bb0000;">lv_draw_sw_ctx_t</code>: | 最初の拡張<code style="color: #bb0000;">lv_draw_sw_ctx_t</code>: | ||
310行目: | 319行目: | ||
} | } | ||
</syntaxhighlight> | </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;"> | <syntaxhighlight lang="C++" style="border: 1px dashed gray;"> | ||
static lv_disp_drv_t drv; | static lv_disp_drv_t drv; | ||
324行目: | 333行目: | ||
lv_disp_drv_register(&drv); | lv_disp_drv_register(&drv); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | このようにして、LVGLが<code style="color: #bb0000;">blend</code> | + | |
+ | |||
+ | このようにして、LVGLが<code style="color: #bb0000;">blend</code>呼び出すと、<code style="color: #bb0000;">my_draw_blend</code>が呼び出され、カスタムGPU操作を実行できます。 | ||
+ | |||
+ | 完全な例を次に示します。 | ||
<syntaxhighlight lang="C++" style="border: 1px dashed gray;"> | <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) | ||
353行目: | 366行目: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
+ | |||
+ | |||
待機コールバックの実装ははるかに簡単です。 | 待機コールバックの実装ははるかに簡単です。 | ||
<syntaxhighlight lang="C++" style="border: 1px dashed gray;"> | <syntaxhighlight lang="C++" style="border: 1px dashed gray;"> | ||
425行目: | 440行目: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | <code style="color: #bb0000;">my_draw_rectblend</code> | + | 必要に応じて、<code style="color: #bb0000;">my_draw_rectblend</code>は<code style="color: #bb0000;">blend</code> コールバック の使用を完全にバイパスできます。 |
|} | |} | ||
:[[App:Library:LVGL:docs:Porting|戻る : Previous]] | :[[App:Library:LVGL:docs:Porting|戻る : Previous]] | ||
435行目: | 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 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. | + | 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 style="color: #bb0000;"> | + | |
+ | |||
+ | 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|戻る : Previous]] | :[[App:Library:LVGL:docs:Porting|戻る : Previous]] |
2022年6月29日 (水) 15:02時点における版
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
レンダラーを必要に応じて拡張/初期化する必要があります。