Skia — este o bibliotecă grafică 2D de înaltă performanță cu sursă deschisă, scrisă în C++, care servește ca motor principal de randare al Flutter. Este responsabilă pentru transformarea widget-urilor și elementelor de interfață de nivel înalt în pixeli pe ecran, suportând randarea software prin CPU și accelerarea hardware prin OpenGL, Vulkan și Metal. Conform Skia Documentation (2025), Skia procesează peste 2 miliarde de cadre randate zilnic pe dispozitivele Android, Chrome și Flutter.
Principalele puncte
Skia — este o bibliotecă grafică 2D multi-platformă dezvoltată de Google și disponibilă sub licența BSD. Oferă o API uniformă pentru desenarea formelor geometrice, textului, imaginilor și umbrelor, abstractizând de backend-ul grafic subiacent. Skia este scrisă în C++ și optimizată pentru a funcționa pe o gamă largă de dispozitive — de la telefoane mobile până la servere.
Istoria Skia a început în 2005 ca o bibliotecă închisă a companiei Skia Inc. În 2007, Google a achiziționat-o, a deschis codul sursă și a început să o utilizeze în produsele sale. Astăzi, Skia este motorul grafic principal al Google Chrome (inclusiv Chrome OS), Android (începând cu versiunea 4.0) și, desigur, Flutter. Biblioteca este susținută de echipa Google și este îmbunătățită constant: se adaugă backend-uri noi, optimizări de performanță și suport pentru API-uri grafice moderne.
Caracteristica cheie a Skia este că nu este doar un set de funcții pentru desenarea primitivelor. Este o conductă grafică completă care include rasterizarea curbelor (căi), anti-aliasing-ul, aplicarea măștilor, procesarea transparenței și corecția culorilor. Skia suportă formatele de imagine PNG, JPEG, WebP și GIF și poate randă textul prin motorul HarfBuzz pentru modelarea glifelor.
Spre deosebire de Cairo (folosit în GTK) sau Quartz 2D (folosit în macOS), Skia a fost proiectată de la început pentru a funcționa pe mai multe platforme cu API-uri grafice diferite. Acest lucru îi oferă un avantaj în framework-urile multi-platformă precum Flutter. Cairo este orientat spre randarea software, în timp ce Skia a suportat accelerarea GPU încă de la început, ceea ce este critic pentru animațiile interfeței.
Arhitectura Skia este construită ca o conductă multi-nivel, fiecare nivel fiind responsabil pentru o anumită etapă de transformare a comenzilor grafice în pixeli. O astfel de structură permite reutilizarea nivelurilor superioare independent de API-ul grafic subiacent.
Nivelul superior — Canvas API — oferă dezvoltatorului o abstractizare pentru desenare. Metodele drawRect, drawCircle, drawPath, drawText acceptă parametri geometrici și stiluri (culoare, transparență, transformări). Canvas transformă aceste comenzi într-o secvență de operații care sunt transmise nivelului Skia Pipeline — un graf intern de comenzi optimizat înainte de execuție.
Nivelul mijlociu — Surface și Device — gestionează bufferul țintă în care are loc randarea. Surface este creat cu specificarea dimensiunii, spațiului de culoare și tipului de backend. Device implementează un backend de randare specific: rasterizatorul CPU (Raster), OpenGL (GL), Vulkan (Vk) sau Metal (Mt). Device conține implementări optimizate ale fiecărei operații de desenare pentru backend-ul respectiv.
Nivelul inferior — Ganesha (backend-ul GPU) — implementează randarea accelerată hardware. Ganesha folosește GPU-ul pentru rasterizarea căilor, umplerea gradientelor și aplicarea efectelor. Acesta colectează comenzile în loturi și minimizează comutarea stării GPU-ului. Pentru fiecare API grafic există propria implementare Ganesha: Skia GL pentru OpenGL, Skia Vulkan pentru Vulkan, Skia Metal pentru Metal.
Skia folosește propriul limbaj de shader SkSL (Skia Shading Language) pentru descrierea efectelor. Codul SkSL este compilat în SPIR-V (reprezentare intermediară), care apoi este tradus în formatul de shader specific backend-ului (GLSL, HLSL, MSL). Aceasta asigură o modalitate uniformă de descriere a efectelor grafice independent de platformă.
Flutter folosește Skia ca motor principal de randare pe toate platformele: Android, iOS, Web, Windows, macOS și Linux. Când o aplicație Flutter randă un cadru, widget-urile sunt transformate într-un arbore RenderObject, care apoi este transmis stratului Engine (în C++), iar Engine folosește Skia pentru randarea finală.
Procesul de randare a unui cadru include mai multe etape. Mai întâi, Flutter Engine construiește o listă de operații (Display List) — o secvență de apeluri Canvas API care descriu ce și cum să fie desenat. Apoi această listă este transmisă către Skia, care împarte operațiile în partiții (zone ale ecranului), le sortează după adâncime și le transmite backend-ului de randare corespunzător. Accelerarea GPU se activează automat dacă Skia detectează un API grafic disponibil.
Unul dintre avantajele cheie ale Skia în Flutter este Flutter Impeller Preview — posibilitatea de previzualizare a shaderelor. Skia compilează shaderele în momentul primei utilizări, ceea ce poate cauza întârzieri (shader jank). Pentru a rezolva această problemă, Flutter trece la Impeller — un nou motor de randare, dar Skia rămâne alegerea principală pentru versiunile stabile ale Flutter.
Flutter folosește conceptul de Layer Tree — un arbore de straturi, fiecare reprezentând o parte a UI-ului. Skia primește comenzi de desenare pentru fiecare strat și determină dacă mai multe straturi pot fi combinate într-o singură trecere de randare. Combinarea straturilor (layer compositing) este o sarcină complexă, deoarece pentru fiecare pixel trebuie luate în considerare transparența și modurile de amestecare (blend modes), pe care Skia le implementează prin shadere GPU.
Skia randă textul prin integrarea cu bibliotecile HarfBuzz (modelare) și icu (unicode). În Flutter, fiecare widget text creează un obiect Paragraph care transformă textul într-o serie de comenzi Skia pentru desenarea glifelor. Skia suportă anti-aliasing-ul subpixel (subpixel anti-aliasing), hinting-ul fonturilor și lucrul cu emoji-uri prin biblioteca SkUnicode.
Performanța Skia este rezultatul a ani de optimizare și a combinației mai multor tehnici: gruparea comenzilor, stocarea în cache a texturilor și minimizarea comutării contextului GPU. Pentru Flutter, acest lucru este critic, deoarece fiecare cadru trebuie randat în 16 ms (60 FPS) sau 8 ms (120 FPS).
| Tehnică | Descriere | Creștere |
|---|---|---|
| Gruparea | Gruparea operațiilor similare într-un singur draw call | până la 3x |
| Cache texturi | Reutilizarea texturilor deja încărcate în GPU | până la 2x |
| Atlas | Combinarea texturilor mici într-una singură mare (texture atlas) | până la 1.5x |
| Deferred rendering | Executarea amânată a comenzilor cu reordonare | până la 2x |
| Shader precompilation | Compilarea prealabilă a shaderelor pentru Spark/Dart | până la 4x |
Conform benchmark-urilor Flutter Team, utilizarea Skia cu accelerare GPU pe dispozitive de gamă medie (Qualcomm Snapdragon 700 series) asigură 60 FPS stabile la randarea interfețelor complexe cu 30+ widget-uri pe ecran. La randarea software (CPU), performanța scade cu 40–60%, dar rămâne acceptabilă pentru ecrane simple.
Principala problemă de performanță a Skia în Flutter este shader jank (întârzierile shaderelor). Când pe ecran apare un nou element vizual cu o combinație necunoscută anterior de efecte, Skia compilează un nou shader pe loc. Compilarea poate dura 50–200 ms, timp în care aplicația pierde cadre. Acest lucru este vizibil mai ales la derularea listelor lungi cu decorațiuni personalizate. Google rezolvă această problemă în Impeller, un nou motor de randare care compilează shaderele în avans.
Skia suportă o gamă largă de platforme, fiecare folosind propriul backend de randare. Alegerea backend-ului este determinată în etapa de construire a Flutter Engine pe baza platformei țintă și a API-urilor grafice disponibile.
Pe Android, Skia funcționează prin OpenGL ES (pe toate dispozitivele) și Vulkan (pe dispozitivele Android 7.0+ cu suport Vulkan). Alegerea backend-ului are loc automat: Vulkan este preferat deoarece oferă o latență mai mică a driverului. Android folosește, de asemenea, Skia pentru randarea UI-ului sistemului prin HWUI (Hardware Accelerated UI), ceea ce face din Skia o parte a sistemului de operare, nu doar a Flutter.
Pe iOS, Skia folosește Metal — API-ul grafic proprietar Apple. Metal oferă acces de nivel scăzut la GPU și cheltuieli generale minime. Înainte de apariția Metal (2014), Skia pe iOS folosea OpenGL ES, dar în versiunile actuale ale Flutter, Metal este singurul backend GPU pentru iOS, oferind o creștere a performanței de până la 30% comparativ cu OpenGL.
Pe desktop, Skia folosește OpenGL (macOS, Linux) și Direct3D 12 (Windows). Suportul pentru Direct3D 12 pentru Windows a fost adăugat în Flutter 3.13 și oferă o îmbunătățire semnificativă a performanței comparativ cu OpenGL pe Windows. Skia suportă, de asemenea, randarea software prin ANGLE (OpenGL peste Direct3D) pe Windows pentru compatibilitate inversă cu driverele grafice vechi.
În Flutter for Web, Skia este compilată în WebAssembly (prin Emscripten) și randă prin WebGL. În acest mod, Skia funcționează complet în browser, fără a folosi cod nativ. Performanța versiunii WebGL a Skia este mai scăzută decât a backend-urilor native, dar pentru majoritatea aplicațiilor web, 60 FPS sunt atinse pe browserele moderne cu accelerare hardware WebGL.
Întrebări frecvente
Shader jank — este o întârziere de randare cauzată de compilarea shaderelor pe loc. Când Skia întâlnește o nouă combinație de efecte vizuale, compilează shaderul, ceea ce poate dura 50–200 ms, timp în care cadrele sunt pierdute. Problema este rezolvată în Impeller prin compilarea prealabilă a shaderelor.
Da, Skia poate fi folosită ca bibliotecă grafică independentă. Este utilizată în Google Chrome, Android, Mozilla Firefox (prin stratul Skia) și în proiecte care necesită grafică 2D de înaltă performanță. Pentru conectare se folosește Skia API, disponibil în C++, Python și prin bindings în alte limbaje.
Flutter folosește un fork al Skia (de obicei ultimul commit stabil din depozitul principal Google). Versiunea este actualizată cu fiecare lansare a Flutter Engine. Commitul actual poate fi găsit în fișierul DEPS din depozitul flutter/engine pe GitHub.
Skia compilează shaderele în timpul execuției, ceea ce cauzează shader jank. Impeller compilează shaderele în avans (offline), folosește SPIR-V și funcționează direct prin Vulkan/Metal/Direct3D 12. Impeller nu suferă de întârzieri ale shaderelor și oferă o performanță mai previzibilă.
Skia în sine nu este un motor de animație — este responsabilă pentru randarea cadrelor individuale. Animația în Flutter este implementată la nivel de framework (AnimationController, Tween), iar Skia asigură randarea rapidă a fiecărui cadru prin Canvas API și accelerarea hardware.
Concluzii
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.