# NanoVG Draw Unit (/integration/embedded_linux/draw_units/draw_nanovg)



Overview [#overview]

NanoVG is a lightweight, antialiased 2D vector graphics library built on OpenGL / OpenGL ES. The NanoVG draw
unit uses it as LVGL's renderer, so widgets and primitives are drawn by the GPU instead of the CPU.

It is the **recommended** GPU renderer on Linux: compared with the
[OpenGL ES draw unit](/integration/embedded_linux/draw_units/draw_opengl) it makes better use of the GPU and
covers more LVGL features. Where the software renderer rasterizes every pixel on the CPU, NanoVG gives you:

* Antialiased path rendering (rectangles, arcs, lines, triangles)
* Image compositing with rotation and scaling
* Text rendering with a font texture atlas
* Box shadows and gradients
* Vector graphics, and 3D rendering

Requirements [#requirements]

* OpenGL 2.0+, OpenGL ES 2.0+, or OpenGL ES 3.0+
* An OpenGL context, created by one of the display drivers listed in
  [OpenGL Overview](/integration/embedded_linux/opengl) or by your own code
* A config with an 8-bit stencil buffer. LVGL's EGL backends require stencil 8 and 4× multisampling when
  choosing a config for NanoVG, so a config lacking them will not be selected.

Configuration [#configuration]

Enable <ApiLink name="LV_USE_DRAW_NANOVG" />.

Options [#options]

| Symbol                       | Default                   | Meaning                                                                             |
| ---------------------------- | ------------------------- | ----------------------------------------------------------------------------------- |
| `LV_NANOVG_BACKEND`          | `LV_NANOVG_BACKEND_GLES2` | Which shader flavour to compile. Must match the context the display driver creates. |
| `LV_NANOVG_IMAGE_CACHE_CNT`  | `128`                     | Number of decoded images kept as GPU textures.                                      |
| `LV_NANOVG_LETTER_CACHE_CNT` | `512`                     | Number of rendered glyphs kept for text drawing.                                    |

`LV_NANOVG_BACKEND` accepts:

| Value                     | Context        |
| ------------------------- | -------------- |
| `LV_NANOVG_BACKEND_GL2`   | OpenGL 2.0     |
| `LV_NANOVG_BACKEND_GL3`   | OpenGL 3.0+    |
| `LV_NANOVG_BACKEND_GLES2` | OpenGL ES 2.0  |
| `LV_NANOVG_BACKEND_GLES3` | OpenGL ES 3.0+ |

<Callout type="warning" title="The backend must match the context">
  `LV_NANOVG_BACKEND` selects which shaders are compiled; it does not create or negotiate a context. Setting a
  flavour the driver's context does not provide gives you shader compilation failures at run time, not a build
  error. The EGL-based drivers request OpenGL ES 3 and fall back to ES 2, so `LV_NANOVG_BACKEND_GLES2` is the
  safe default.
</Callout>

Supported Features [#supported-features]

| Feature         | Notes                                                              |
| --------------- | ------------------------------------------------------------------ |
| Fill            | Solid colors, linear and radial gradients                          |
| Border          | Rounded rectangles with configurable width                         |
| Box Shadow      | Hardware-accelerated                                               |
| Images          | Rotation, scaling, tiling, recoloring                              |
| Labels          | Font rendering with a texture atlas                                |
| Lines           | Antialiased, configurable width                                    |
| Arcs            | Antialiased arc segments                                           |
| Triangles       | Filled                                                             |
| Masks           | Rectangle masks for clipping                                       |
| Layers          | Off-screen rendering into an FBO                                   |
| Canvas          | Direct drawing into canvas buffers                                 |
| Vector Graphics | Path rendering — requires <ApiLink name="LV_USE_VECTOR_GRAPHIC" /> |
| 3D              | glTF models, see [glTF](/libs/gltf)                                |

Image formats uploaded without conversion [#image-formats-uploaded-without-conversion]

| LVGL format                                 | GL handling                | Notes                                   |
| ------------------------------------------- | -------------------------- | --------------------------------------- |
| <ApiLink name="LV_COLOR_FORMAT_A8" />       | Alpha texture              | Tinted in the shader                    |
| <ApiLink name="LV_COLOR_FORMAT_ARGB8888" /> | BGR→RGB swizzle            | Premultiplication handled in the shader |
| <ApiLink name="LV_COLOR_FORMAT_XRGB8888" /> | BGR→RGB, alpha forced to 1 | X channel ignored                       |
| <ApiLink name="LV_COLOR_FORMAT_RGB888" />   | BGR→RGB swizzle            | No alpha                                |
| <ApiLink name="LV_COLOR_FORMAT_RGB565" />   | Direct upload              | LVGL uses a BGR565 layout               |

Anything else is converted before upload, which costs CPU time per image. Prefer one of the formats above for
assets you draw often.

Performance Tips [#performance-tips]

* **Minimize layer usage.** Each layer means a framebuffer object switch.
* **Use premultiplied alpha.** Set `LV_IMAGE_FLAGS_PREMULTIPLIED` on images you have pre-processed.
* **Let the caches work.** Textures and glyphs are cached automatically; recreating images defeats that.
  Raise `LV_NANOVG_IMAGE_CACHE_CNT` or `LV_NANOVG_LETTER_CACHE_CNT` if your UI requires more than the default value.
* **Batch similar styles.** Widgets with matching styles batch better on the GPU.

Limitations [#limitations]

* **Gradients** are limited to two colors; LVGL's API allows more stops.
* **Layer and canvas readback** goes through `glReadPixels`, which is slow. Avoid it per frame.

See Also [#see-also]

* [OpenGL Overview](/integration/embedded_linux/opengl) - how drivers and draw units fit together
* [OpenGL ES Draw Unit](/integration/embedded_linux/draw_units/draw_opengl) - the texture-caching alternative
* [glTF](/libs/gltf) - 3D model rendering, which requires a GPU renderer
* [EGL](/integration/embedded_linux/drivers/egl) - context creation, including headless off-screen rendering
* [DRM](/integration/embedded_linux/drivers/drm) - production display driver with an EGL backend
