# NXP G2D GPU (/integration/chip_vendors/nxp/g2d_gpu)



On NXP i.MX MPU platforms, the acceleration can be done hardware independently by the NXP G2D
library. LVGL integrates it as a [draw unit](/main-modules/draw), so several drawing features are
offloaded to the G2D engine while the CPU is available for other operations. Linux is required to
block the LVGL drawing thread and switch to another task or suspend the CPU for power savings.

Basic configuration [#basic-configuration]

* Select the NXP G2D engine in `lv_conf.h`: Set <ApiLink name="LV_USE_DRAW_G2D" /> to `1`.
* Enable G2D asserts in `lv_conf.h`: Set <ApiLink name="LV_USE_G2D_ASSERT" /> to `1`.
  There are a few G2D assertions that can stop the program execution in case the
  <ApiLink name="LV_ASSERT_HANDLER" /> is set to `while(1);` (Halt by default). Otherwise,
  only an error message is logged via `LV_LOG_ERROR`.
* <ApiLink name="LV_G2D_HASH_TABLE_SIZE" /> sets the maximum number of buffers mapped for the
  draw unit, including frame buffers and assets. Drawing asserts once the table is full.

Basic initialization [#basic-initialization]

G2D draw initialization is done automatically in <ApiLink name="lv_init" /> once the
G2D is enabled as a draw unit, no user code is required:

```c title=" " lineNumbers=1
#if LV_USE_DRAW_G2D
  lv_draw_g2d_init();
#endif
```

During G2D initialization, a new draw unit `lv_draw_g2d_unit_t` will be created
with the additional callbacks, if <ApiLink name="LV_USE_DRAW_G2D" /> is set to `1`:

```c title=" " lineNumbers=1
lv_draw_g2d_unit_t * draw_g2d_unit = lv_draw_create_unit(sizeof(lv_draw_g2d_unit_t));
draw_g2d_unit->base_unit.evaluate_cb = _g2d_evaluate;
draw_g2d_unit->base_unit.dispatch_cb = _g2d_dispatch;
draw_g2d_unit->base_unit.delete_cb = _g2d_delete;
```

and an additional thread `_g2d_render_thread_cb()` will be spawned in order to
handle the supported draw tasks.

```c title=" " lineNumbers=1
#if LV_USE_G2D_DRAW_THREAD
  lv_thread_init(&draw_g2d_unit->thread, "g2ddraw", LV_THREAD_PRIO_HIGH, _g2d_render_thread_cb, 2 * 1024, draw_g2d_unit);
#endif
```

If `LV_USE_G2D_DRAW_THREAD` is not defined, then no additional draw thread will be created
and the G2D drawing task will get executed on the same LVGL main thread.

`_g2d_evaluate()` will get called after each task is being created and will
analyze if the task is supported by G2D or not. If it is supported, then a
preferred score and the draw unit id will be set to the task. A `score` equal
to `100` is the default CPU score. Smaller score means that G2D is capable of
drawing it faster.

`_g2d_dispatch()` is the G2D dispatcher callback, it will take a ready to draw
task (having the `DRAW_UNIT_ID_G2D` set) and will pass the task to the G2D draw
unit for processing.

`_g2d_delete()` will cleanup the G2D draw unit.

Features supported [#features-supported]

Supported draw tasks are available in `src/draw/nxp/g2d/lv_draw_g2d.c`:

```c title=" " lineNumbers=1
switch(t->type) {
    case LV_DRAW_TASK_TYPE_FILL:
        lv_draw_g2d_fill(u, t->draw_dsc, &t->area);
        break;
    case LV_DRAW_TASK_TYPE_IMAGE:
        lv_draw_g2d_img(u, t->draw_dsc, &t->area);
        break;
    default:
        break;
}
```

* Fill area with color (w/o radius, w/o gradient) + optional opacity.
* Blit source image ARGB8888 over destination ARGB8888 + optional opacity.
* Scale source image ARGB8888.

Known limitations [#known-limitations]

* G2D can only rotate at 90° angles.
* Rotation is not supported for images unaligned to blocks of 16x16 pixels. G2D
  is set to process 16x16 blocks to optimize the system for memory bandwidth and
  image processing time. The output engine essentially truncates any output
  pixels after the desired number of pixels has been written. When rotating a
  source image and the output is not divisible by the block size, the incorrect
  pixels could be truncated and the final output image can look shifted.
* Recolor or transformation for images w/ opacity or alpha channel can't be
  obtained in a single G2D pipeline configuration. Two or multiple steps would
  be required.
* Buffer address must be aligned to 64 bytes: set <ApiLink name="LV_DRAW_BUF_ALIGN" />
  to `64` in `lv_conf.h`.
  No stride alignment is required: set <ApiLink name="LV_DRAW_BUF_STRIDE_ALIGN" /> to
  `1` in `lv_conf.h`.

Project setup [#project-setup]

Add the G2D related source files (and corresponding headers if available) to the project:

* `src/draw/nxp/g2d/lv_draw_buf_g2d.c`: draw buffer callbacks
* `src/draw/nxp/g2d/lv_draw_g2d_fill.c`: fill area
* `src/draw/nxp/g2d/lv_draw_g2d_img.c`: blit image (w/ optional recolor or transformation)
* `src/draw/nxp/g2d/lv_draw_g2d.c`: draw unit initialization
* `src/draw/nxp/g2d/lv_g2d_buf_map.c`: hash map for G2D buffers
* `src/draw/nxp/g2d/lv_g2d_utils.c`: function helpers
