Engine Layer #
Flutter Engine adalah komponen yang paling jarang disentuh developer secara langsung, namun paling menentukan performa aplikasi. Seluruhnya ditulis dalam C++, bersifat platform-agnostic, dan bertanggung jawab atas segala sesuatu mulai dari menjalankan kode Dart hingga mengubah instruksi gambar menjadi piksel aktual di layar.
Gambaran Engine Layer #
Engine Layer menerima instruksi dari Framework Layer (melalui dart:ui) dan mengeksekusinya di level paling rendah sebelum menyerahkan hasil akhirnya ke Embedder:
Framework (Dart)
|
| dart:ui API calls
v
+------------------------------------------+
| Flutter Engine (C++) |
| |
| +-------------+ +------------------+ |
| | Dart Runtime| | Rendering Engine | |
| | & Compiler | | Skia / Impeller | |
| +-------------+ +------------------+ |
| |
| +-------------+ +------------------+ |
| | Text Layout | | Accessibility | |
| | SkParagraph | | & I/O | |
| +-------------+ +------------------+ |
| |
| +--------------------------------------+|
| | Plugin / Channel Architecture ||
| +--------------------------------------+|
+------------------------------------------+
|
| Frame buffer / Surface
v
Platform Embedder
Dart Runtime & Compile Toolchain #
Komponen pertama dan paling fundamental di Engine adalah Dart Runtime — sistem yang menjalankan kode Dart aplikasimu.
Dart VM dan Isolate #
Dart Runtime menjalankan kode dalam unit bernama Isolate — mirip thread, tapi tanpa shared memory. Setiap Isolate punya heap memorinya sendiri, sehingga tidak ada race condition antar isolate.
Flutter App (single process)
+------------------+ +-------------------+
| Main Isolate | | Worker Isolate |
| (UI Thread) | | (Background) |
| | | |
| Widget build | | Heavy computation|
| State updates | | JSON parsing |
| Gesture handling| | Image decoding |
+------------------+ +-------------------+
| |
+-------- Port ----------+
(komunikasi via
message passing,
bukan shared memory)
Komunikasi antar Isolate hanya bisa dilakukan lewat Port dengan cara mengirim pesan — bukan berbagi variabel langsung. Ini membuat kode Dart inherently thread-safe.
Compile Toolchain #
Engine menyertakan dua jalur kompilasi sesuai kebutuhan:
Development (Debug):
Dart Source --> Dart VM (JIT) --> Machine Code (runtime)
Keuntungan: Hot Reload, debugging lengkap
Production (Release):
Dart Source --> gen_snapshot (AOT) --> .so / .dylib
Keuntungan: startup cepat, performa konsisten, ukuran lebih kecil
gen_snapshot adalah tool AOT compiler Flutter. Ia menghasilkan dua file:
- Snapshot data — berisi heap awal aplikasi (object yang dibuat saat startup)
- Snapshot instructions — berisi machine code yang telah dikompilasi
Rendering Engine: Skia vs Impeller #
Ini adalah komponen yang paling banyak diperbincangkan dalam evolusi Flutter. Rendering engine bertanggung jawab mengubah layer tree (hasil dari Framework) menjadi piksel di layar.
Skia — Engine Lama yang Terbukti #
Skia adalah 2D graphics library open-source yang dikembangkan Google, digunakan tidak hanya di Flutter tapi juga di Chrome, Android, dan YouTube. Flutter menggunakan Skia sejak awal.
Cara Skia bekerja (Immediate Mode Rendering):
Frame N: Gambar SEMUA elemen dari awal
Frame N+1: Gambar SEMUA elemen dari awal lagi
Frame N+2: Gambar SEMUA elemen dari awal lagi
(meskipun hanya 1 elemen yang berubah)
Pendekatan ini sederhana tapi boros — setiap frame digambar ulang secara penuh.
Masalah utama Skia: Shader Compilation Jank
Skia mengkompilasi shader GPU saat runtime — tepat ketika shader tersebut pertama kali dibutuhkan. Ini menyebabkan jeda (jank) yang terasa saat animasi baru pertama kali dijalankan:
Animasi pertama kali dijalankan:
Frame 1: Skia compile shader... (16ms lebih) --> JANK terlihat
Frame 2: Shader sudah ada di cache --> 16ms normal
Frame 3: 16ms normal
Frame 4: 16ms normal
Impeller — Engine Baru Flutter #
Impeller adalah rendering engine yang dibangun khusus untuk Flutter, dikembangkan sejak 2019 dan mulai diprototiping secara serius pada 2021. Impeller dirancang untuk menyelesaikan masalah fundamental Skia.
Cara Impeller bekerja (Retained Mode Rendering):
Frame N: Gambar semua elemen, simpan state ke GPU buffer
Frame N+1: Cek elemen mana yang BERUBAH,
gambar ulang HANYA elemen tersebut,
reuse GPU buffer untuk yang tidak berubah
Frame N+2: Sama -- hanya gambar yang berubah
(jauh lebih efisien)
Solusi Impeller untuk Shader Jank:
SKIA (JIT Shader):
Runtime --> Shader dibutuhkan --> Compile sekarang --> Jank!
IMPELLER (AOT Shader):
Build time --> Semua shader dikompilasi --> Tidak ada kompilasi saat runtime
Runtime --> Shader langsung tersedia --> Tidak ada jank!
Impeller mengkompilasi semua shader yang dibutuhkan saat engine dikompilasi (bukan saat app berjalan). Hasilnya: tidak ada shader compilation jank sama sekali.
Keunggulan teknis Impeller lainnya:
// 1. Tile-based rendering
// Impeller membagi frame menjadi tile (misal 256x256 px)
// Hanya tile yang berubah kontennya yang di-rasterisasi ulang
// 2. GPU resource management yang lebih baik
// Semua GPU resource (texture, buffer) diberi label dan dilacak
// Memory leak lebih mudah dideteksi
// 3. Binary size lebih kecil
// Skia menyertakan machinery shader compilation (~17% ukuran engine)
// Impeller tidak perlu itu -- hanya ~100kb overhead (compressed)
// 4. 3D rendering support (baru)
// Impeller membuka jalan untuk Flutter GPU API
// Mendukung rendering 3D scene via Flutter Scene
Status Impeller saat ini (2025):
| Platform | Backend GPU | Status |
|---|---|---|
| iOS | Metal | Default sejak Flutter 3.29 |
| Android API 29+ | Vulkan | Default sejak Flutter 3.27 |
| Android API < 29 | OpenGL ES | Fallback otomatis |
| macOS | Metal | Behind flag |
| Web | CanvasKit/Skwasm | Belum (masih Skia) |
| Windows / Linux | Vulkan / OpenGL | Dalam pengembangan |
Apakah Impeller Sepenuhnya Lepas dari Skia?
Tidak sepenuhnya. Meskipun Impeller tidak menggunakan Skia untuk rendering grafis, Flutter masih menggunakan SkParagraph (bagian dari Skia) untuk text shaping dan layout. Impeller melakukan text rendering, tapi untuk menentukan posisi setiap karakter dan shaping font, SkParagraph masih digunakan. Ini adalah detail implementasi yang transparan bagi developer.
Text Layout — SkParagraph #
Text rendering di Flutter lebih kompleks dari yang terlihat. Menampilkan teks bukan sekadar “gambar huruf” — ada banyak proses di baliknya:
Teks "Halo 👋 Flutter"
|
v
1. Unicode segmentation --> pisah karakter, emoji, whitespace
|
v
2. BiDi (Bidirectional) --> deteksi arah teks (LTR/RTL)
|
v
3. Font selection --> pilih font yang tepat per karakter
|
v
4. Text shaping (HarfBuzz)--> konversi codepoint ke glyph
|
v
5. Glyph layout --> hitung posisi x,y setiap glyph
|
v
6. Text rendering --> gambar glyph ke canvas (Impeller/Skia)
HarfBuzz adalah library text shaping open-source yang digunakan oleh SkParagraph untuk langkah 4 — menentukan bentuk akhir karakter setelah mempertimbangkan ligatur, kerning, dan aturan tipografi kompleks.
Dari sisi developer, semua kompleksitas ini tersembunyi di balik widget Text yang sederhana:
// Semua proses shaping, layout, dan rendering terjadi otomatis
Text(
'مرحبا Flutter', // teks Arab (RTL) -- ditangani otomatis
style: TextStyle(
fontSize: 24,
fontFamily: 'Cairo',
fontWeight: FontWeight.bold,
),
textDirection: TextDirection.rtl,
)
Compositor dan Layer Tree #
Sebelum diserahkan ke rendering engine, Framework menghasilkan sebuah Layer Tree — representasi terstruktur dari UI yang dioptimalkan untuk compositing GPU.
Jenis-jenis Layer #
Layer Tree:
TransformLayer --> transformasi (translate, rotate, scale)
|-- OffsetLayer --> pergeseran posisi
|-- ClipRectLayer --> clipping rectangular
|-- ClipPathLayer --> clipping dengan path kustom
|-- OpacityLayer --> efek transparansi
|-- PictureLayer --> konten yang digambar (hasil CustomPainter)
|-- TextureLayer --> konten video/kamera (external texture)
|-- PlatformViewLayer--> embedded native view
Proses Compositing #
Widget Tree (Framework)
|
v
RenderObject Tree (layout + paint)
|
v
Layer Tree (compositing hints)
|
v
Engine: Compositor "flow"
|
v
GPU Command Buffer
|
v
Impeller/Skia rasterisasi
|
v
Frame Buffer
|
v
Display (via Embedder)
Compositor Flutter disebut “flow” — nama internal yang digunakan oleh tim Flutter engine. Flow menerima layer tree dari Framework dan bertanggung jawab mengorkestrasi seluruh proses rasterisasi di GPU thread, terpisah dari UI thread.
Task Runners — Empat Thread Flutter #
Engine Flutter beroperasi di empat thread (task runner) yang berbeda, masing-masing dengan tanggung jawab spesifik:
+------------------+------------------+------------------+------------------+
| UI Runner | Raster Runner | IO Runner | Platform Runner |
+------------------+------------------+------------------+------------------+
| Menjalankan kode | Rasterisasi layer| Operasi I/O | Komunikasi |
| Dart (main | tree ke GPU | (load gambar, | dengan platform |
| isolate) | | asset, network) | native |
| | | | |
| build() | Impeller/Skia | Image decode | Platform Channel |
| setState() | draw calls | Asset loading | Method Channel |
| layout | GPU submission | File I/O | Lifecycle events |
+------------------+------------------+------------------+------------------+
↑ ↑ ↑ ↑
60 FPS sync vsync background platform
budget GPU work I/O ops events
Mengapa pemisahan ini penting?
Jika rasterisasi (GPU work) dilakukan di thread yang sama dengan kode Dart, setiap operasi GPU yang berat akan memblokir UI thread dan menyebabkan jank. Dengan memisahkan Raster Runner dan UI Runner, keduanya bisa berjalan secara paralel.
dart:ui — Interface antara Engine dan Framework #
Engine mengekspos seluruh fungsionalitasnya ke Framework melalui library dart:ui. Ini adalah “kontrak” antara C++ dan Dart — API level terendah yang bisa diakses dari kode Dart.
import 'dart:ui';
// Contoh API dart:ui (biasanya kamu tidak perlu ini langsung)
// Akses window/display info
final double devicePixelRatio = PlatformDispatcher.instance.views.first.devicePixelRatio;
final Size screenSize = PlatformDispatcher.instance.views.first.physicalSize;
// Low-level canvas operations
void renderCustom(Canvas canvas) {
// Paint dengan shader kustom
final shader = FragmentProgram.fromAsset('shaders/my_shader.frag');
final paint = Paint()..shader = shader.fragmentShader();
canvas.drawRect(
Rect.fromLTWH(0, 0, 200, 200),
paint,
);
}
// Image dari bytes
Future<Image> loadImageFromBytes(Uint8List bytes) async {
final codec = await instantiateImageCodec(bytes);
final frame = await codec.getNextFrame();
return frame.image;
}
Flutter GPU — Masa Depan Rendering Kustom #
Fitur terbaru yang dibawa Impeller adalah Flutter GPU API — antarmuka low-level untuk menulis rendering kustom menggunakan Dart dan GLSL shader secara langsung.
import 'dart:ui' as ui;
// Flutter GPU memungkinkan rendering 3D dan efek grafis kompleks
// yang sebelumnya tidak mungkin dilakukan dari Dart
// (masih eksperimental per 2025)
// Contoh konseptual penggunaan Flutter GPU:
void renderWith3D(gpu.RenderPass renderPass) {
renderPass
..bindPipeline(myPipeline)
..bindVertexBuffer(vertexBuffer)
..draw();
}
Di atas Flutter GPU, tim Flutter sedang membangun Flutter Scene — library untuk mengimpor dan merender model 3D dalam format glTF (standar open 3D dari Khronos Group).
Ringkasan #
- Flutter Engine ditulis dalam C++, bersifat platform-agnostic, dan bertanggung jawab dari Dart runtime hingga piksel di layar.
- Dart Runtime menjalankan kode dalam Isolate — unit eksekusi tanpa shared memory yang inherently thread-safe.
- Skia menggunakan Immediate Mode Rendering dan kompilasi shader saat runtime (JIT) — penyebab utama shader compilation jank.
- Impeller menggunakan Retained Mode Rendering dengan tile-based approach dan kompilasi shader saat build time (AOT) — menghilangkan jank sepenuhnya.
- Impeller adalah default di iOS (sejak Flutter 3.29) dan Android API 29+ (sejak Flutter 3.27).
- Text rendering melibatkan pipeline panjang: Unicode segmentation → BiDi → font selection → shaping (HarfBuzz) → layout → rendering.
- Engine beroperasi di empat task runner terpisah: UI, Raster, IO, dan Platform — memastikan UI thread tidak pernah diblokir pekerjaan GPU.
dart:uiadalah kontrak antara Engine (C++) dan Framework (Dart) — API level terendah yang bisa diakses dari Dart.- Flutter GPU API membuka kemungkinan rendering 3D dan shader kustom langsung dari Dart — masa depan rendering Flutter.
← Sebelumnya: Framework Layer Berikutnya: Platform Embedder →