Skia — är ett högpresterande 2D-grafikbibliotek med öppen källkod, skrivet i C++, som fungerar som Flutters primära renderingsmotor. Det ansvarar för att omvandla högnivåwidgets och gränssnittselement till pixlar på skärmen, med stöd för programvarurendering via CPU och hårdvaruacceleration via OpenGL, Vulkan och Metal. Enligt Skia Documentation (2025) bearbetar Skia över 2 miljarder renderade bildrutor dagligen på Android-, Chrome- och Flutter-enheter.
Huvudpunkter
Skia — är ett plattformsoberoende 2D-grafikbibliotek utvecklat av Google och tillgängligt under BSD-licens. Det tillhandahåller ett enhetligt API för att rita geometriska former, text, bilder och skuggor, med abstraktion från den underliggande grafikbackend. Skia är skrivet i C++ och optimerat för att fungera på ett brett spektrum av enheter — från mobiltelefoner till servrar.
Historien om Skia började 2005 som ett slutet bibliotek från företaget Skia Inc. 2007 köptes det av Google, som öppnade källkoden och började använda det i sina produkter. Idag är Skia den primära grafikmotorn för Google Chrome (inklusive Chrome OS), Android (från version 4.0) och naturligtvis Flutter. Biblioteket stöds av Google-teamet och förbättras ständigt: nya backends, prestandaoptimeringar och stöd för moderna grafik-API:er läggs till.
Nyckelfunktionen hos Skia är att det inte bara är en samling funktioner för att rita primitiver. Det är en komplett grafikpipelinje som inkluderar rastrering av kurvor (banor), kantutjämning (anti-aliasing), applicering av masker, transparenshantering och färgkorrigering. Skia stöder bildformaten PNG, JPEG, WebP och GIF, och kan också rendera text via HarfBuzz-motorn för glyfformning.
Till skillnad från Cairo (används i GTK) eller Quartz 2D (används i macOS) designades Skia från början för att fungera på flera plattformar med olika grafik-API:er. Detta ger det en fördel i plattformsoberoende ramverk som Flutter. Cairo är inriktat på programvarurendering, medan Skia stödde GPU-acceleration från början, vilket är avgörande för gränssnittsanimationer.
Skias arkitektur är byggd som en flerskiktad pipeline, där varje lager ansvarar för ett specifikt stadium av omvandlingen av grafikkommandon till pixlar. En sådan struktur möjliggör återanvändning av de övre lagren oberoende av det underliggande grafik-API:et.
Det övre lagret — Canvas API — ger utvecklaren en abstraktion för ritning. Metoderna drawRect, drawCircle, drawPath, drawText accepterar geometriska parametrar och stilar (färg, transparens, transformationer). Canvas omvandlar dessa kommandon till en sekvens av operationer som skickas till Skia Pipeline-lagret — en intern kommandograf som optimeras före exekvering.
Mellanskiktet — Surface och Device — hanterar målbufferten där rendering sker. Surface skapas med angivelse av storlek, färgrymd och backendtyp. Device implementerar en specifik renderingsbackend: CPU-rastrerare (Raster), OpenGL (GL), Vulkan (Vk) eller Metal (Mt). Device innehåller optimerade implementeringar av varje ritningsoperation för den specifika backend.
Det nedre lagret — Ganesha (GPU-backend) — implementerar hårdvaruaccelererad rendering. Ganesha använder GPU:n för rastrering av banor, fyllning av gradienter och applicering av effekter. Den samlar kommandon i batchar och minimerar GPU-statusväxling. För varje grafik-API finns en egen Ganesha-implementering: Skia GL för OpenGL, Skia Vulkan för Vulkan, Skia Metal för Metal.
Skia använder sitt eget shaderspråk SkSL (Skia Shading Language) för att beskriva effekter. SkSL-kod kompileras till SPIR-V (mellanrepresentation), som sedan översätts till det backendspecifika shaderformatet (GLSL, HLSL, MSL). Detta ger ett enhetligt sätt att beskriva grafiska effekter oberoende av plattform.
Flutter använder Skia som primär renderingsmotor på alla plattformar: Android, iOS, Web, Windows, macOS och Linux. När en Flutter-app renderar en bildruta omvandlas widgets till ett RenderObject-träd, som sedan skickas till Engine-lagret (i C++), och Engine använder Skia för slutlig rendering.
Processen för att rendera en bildruta omfattar flera steg. Först bygger Flutter Engine en operationslista (Display List) — en sekvens av Canvas API-anrop som beskriver vad och hur som ska ritas. Sedan skickas listan till Skia, som delar upp operationerna i partitioner (skärmområden), sorterar dem efter djup och skickar till lämplig renderingsbackend. GPU-acceleration aktiveras automatiskt om Skia upptäcker ett tillgängligt grafik-API.
En av de viktigaste fördelarna med Skia i Flutter är Flutter Impeller Preview — möjligheten att förhandsgranska shaders. Skia kompilerar shaders vid första användningstillfället, vilket kan orsaka fördröjningar (shader jank). För att lösa detta problem övergår Flutter till Impeller — en ny renderingsmotor, men Skia förblir det primära valet för stabila versioner av Flutter.
Flutter använder konceptet Layer Tree — ett träd av lager, där varje representerar en del av UI. Skia får ritkommandon för varje lager och avgör om flera lager kan kombineras i en enda renderingsomgång. Lagersammansättning (layer compositing) är en komplex uppgift, eftersom varje pixel måste ta hänsyn till transparens och blandningslägen (blend modes), som Skia implementerar via GPU-shaders.
Skia renderar text genom integration med biblioteken HarfBuzz (formning) och icu (unicode). I Flutter skapar varje textwidget ett Paragraph-objekt som omvandlar text till en serie Skia-kommandon för att rita glyfer. Skia stöder subpixel-kantutjämning (subpixel anti-aliasing), font-hinting och arbete med emoji via SkUnicode-biblioteket.
Skia prestanda är resultatet av flera års optimering och en kombination av flera tekniker: batchning av kommandon, cachning av texturer och minimering av GPU-kontextväxling. För Flutter är detta avgörande, eftersom varje bildruta måste renderas inom 16 ms (60 FPS) eller 8 ms (120 FPS).
| Teknik | Beskrivning | Ökning |
|---|---|---|
| Batchning | Gruppering av liknande operationer i ett draw call | upp till 3x |
| Texturcache | Återanvändning av redan laddade texturer i GPU | upp till 2x |
| Atlas | Sammanfogning av små texturer till en stor (texture atlas) | upp till 1.5x |
| Deferred rendering | Fördröjd exekvering av kommandon med omordning | upp till 2x |
| Shader precompilation | Förkompilering av shaders för Spark/Dart | upp till 4x |
Enligt riktmärken från Flutter Team ger användning av Skia med GPU-acceleration på medelklassenheter (Qualcomm Snapdragon 700 series) stabila 60 FPS vid rendering av komplexa gränssnitt med 30+ widgets på skärmen. Vid programvarurendering (CPU) sjunker prestandan med 40–60%, men förblir acceptabel för enkla skärmar.
Det främsta prestandaproblemet med Skia i Flutter är shader jank (shader-fördröjningar). När ett nytt visuellt element med en okänd kombination av effekter visas på skärmen, kompilerar Skia en ny shader i farten. Kompilering kan ta 50–200 ms, under vilka applikationen hoppar över bildrutor. Detta är särskilt märkbart vid scrollning av långa listor med anpassade dekorationer. Google löser detta problem i Impeller, en ny renderingsmotor som kompilerar shaders i förväg.
Skia stöder ett brett spektrum av plattformar, där var och en använder sin egen renderingsbackend. Valet av backend bestäms i byggfasen av Flutter Engine baserat på målplattformen och tillgängliga grafik-API:er.
På Android fungerar Skia via OpenGL ES (på alla enheter) och Vulkan (på enheter med Android 7.0+ och Vulkan-stöd). Backend-valet sker automatiskt: Vulkan är att föredra eftersom det ger lägre driverfördröjning. Android använder också Skia för rendering av systemets UI via HWUI (Hardware Accelerated UI), vilket gör Skia till en del av operativsystemet, inte bara Flutter.
På iOS använder Skia Metal — Apples proprietära grafik-API. Metal ger lågnivååtkomst till GPU:n och minimal överhead. Fre Metal (2014) använde Skia på iOS OpenGL ES, men i nuvarande versioner av Flutter är Metal den enda GPU-backend för iOS, vilket ger en prestandaökning på upp till 30% jämfört med OpenGL.
På skrivbordet använder Skia OpenGL (macOS, Linux) och Direct3D 12 (Windows). Stöd för Direct3D 12 för Windows lades till i Flutter 3.13 och ger en betydande prestandaförbättring jämfört med OpenGL på Windows. Skia stöder också programvarurendering via ANGLE (OpenGL ovanpå Direct3D) på Windows för bakåtkompatibilitet med gamla grafikdrivrutiner.
I Flutter for Web kompileras Skia till WebAssembly (via Emscripten) och renderar via WebGL. I detta läge fungerar Skia helt i webbläsaren, utan att använda inbyggd kod. Prestandan för WebGL-versionen av Skia är lägre än för inbyggda backends, men för de flesta webbapplikationer uppnås 60 FPS på moderna webbläsare med hårdvaruacceleration för WebGL.
Vanliga frågor
Shader jank — är en renderingsfördröjning på grund av kompilering av shaders i farten. När Skia stöter på en ny kombination av visuella effekter kompilerar det en shader, vilket kan ta 50–200 ms, under vilka bildrutor hoppas över. Problemet löses i Impeller genom förkompilering av shaders.
Ja, Skia kan användas som ett fristående grafikbibliotek. Det används i Google Chrome, Android, Mozilla Firefox (via Skia-lagret) och i projekt som kräver högpresterande 2D-grafik. För anslutning används Skia API, tillgängligt i C++, Python och via bindings i andra språk.
Flutter använder en fork av Skia (vanligtvis den senaste stabila commiten från Googles huvudarkiv). Versionen uppdateras med varje Flutter Engine-utgåva. Den aktuella commiten finns i filen DEPS i arkivet flutter/engine på GitHub.
Skia kompilerar shaders under körning, vilket orsakar shader jank. Impeller kompilerar shaders i förväg (offline), använder SPIR-V och fungerar direkt via Vulkan/Metal/Direct3D 12. Impeller lider inte av shader-fördröjningar och ger mer förutsägbar prestanda.
Skia är i sig ingen animationsmotor — den ansvarar för rendering av enskilda bildrutor. Animation i Flutter implementeras på ramverksnivå (AnimationController, Tween), medan Skia säkerställer snabb rendering av varje bildruta via Canvas API och hårdvaruacceleration.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.