Senkronizasyon çerçevesi, Android grafik sistemindeki farklı eşzamansız işlemler arasındaki bağımlılıkları açıkça tanımlar. Çerçeve, bileşenlerin arabelleklerin ne zaman serbest bırakıldığını belirtmesine olanak tanıyan bir API sağlar. Çerçeve aynı zamanda senkronizasyon temellerinin çekirdekten kullanıcı alanına sürücüler arasında ve kullanıcı alanı işlemlerinin kendisi arasında aktarılmasına da olanak tanır.
Örneğin, bir uygulama GPU'da gerçekleştirilecek işi sıraya koyabilir. GPU bu görüntüyü çizmeye başlar. Görüntü henüz belleğe çekilmemiş olsa da arabellek işaretçisi, GPU işinin ne zaman biteceğini gösteren bir çitle birlikte pencere dizgisine iletilir. Pencere dizgicisi önceden işlemeye başlar ve işi ekran denetleyicisine aktarır. Benzer şekilde CPU işi de önceden yapılır. GPU bittiğinde ekran denetleyicisi görüntüyü hemen görüntüler.
Senkronizasyon çerçevesi aynı zamanda uygulayıcıların kendi donanım bileşenlerindeki senkronizasyon kaynaklarından yararlanmasına da olanak tanır. Son olarak çerçeve, hata ayıklamaya yardımcı olmak için grafik ardışık düzenine görünürlük sağlar.
Açık senkronizasyon
Açık senkronizasyon, grafik arabellek üreticilerinin ve tüketicilerinin, bir arabellek kullanarak işleri bittiğinde sinyal vermelerini sağlar. Açık senkronizasyon çekirdek alanında uygulanır.
Açık senkronizasyonun avantajları şunları içerir:
- Cihazlar arasında daha az davranış değişikliği
- Daha iyi hata ayıklama desteği
- Geliştirilmiş test ölçümleri
Senkronizasyon çerçevesinin üç nesne türü vardır:
-
sync_timeline
-
sync_pt
-
sync_fence
senkronizasyon_zaman çizelgesi
sync_timeline
satıcıların GL bağlamı, ekran denetleyicisi veya 2D ekran görüntüsü gibi her sürücü örneği için uygulaması gereken monoton olarak artan bir zaman çizelgesidir. sync_timeline
belirli bir donanım parçası için çekirdeğe gönderilen işleri sayar. sync_timeline
işlemlerin sırası hakkında garantiler sağlar ve donanıma özgü uygulamalara olanak tanır.
sync_timeline
uygularken bu yönergeleri izleyin:
- Hata ayıklamayı kolaylaştırmak için tüm sürücülere, zaman çizelgelerine ve sınırlamalara yararlı adlar sağlayın.
- Hata ayıklama çıktısını daha okunabilir hale getirmek için
timeline_value_str
vept_value_str
operatörlerini zaman çizelgelerine uygulayın. - İstenirse, GL kitaplığı gibi kullanıcı alanı kitaplıklarına özel zaman çizelgesi verilerine erişim sağlamak için dolgu
driver_data
uygulayın.data_driver
satıcıların değişmezsync_fence
vesync_pts
hakkındaki bilgileri aktararak bunlara dayalı komut satırları oluşturmalarına olanak tanır. - Kullanıcı alanının açıkça bir çit oluşturmasına veya sinyal vermesine izin vermeyin. Açıkça sinyaller/çitler oluşturmak, boru hattı işlevselliğini durduran bir hizmet reddi saldırısıyla sonuçlanır.
-
sync_timeline
,sync_pt
veyasync_fence
öğelerine açıkça erişmeyin. API gerekli tüm işlevleri sağlar.
senkronizasyon_pt
sync_pt
sync_timeline
çizelgesindeki tek bir değer veya noktadır. Bir noktanın üç durumu vardır: aktif, sinyalli ve hata. Noktalar aktif durumda başlar ve sinyal verilen veya hata durumlarına geçiş yapar. Örneğin, bir görüntü tüketicisinin artık ara belleğe ihtiyacı kalmadığında, bir sync_pt
sinyali gönderilir, böylece görüntü üreticisi ara belleğe tekrar yazmanın sorun olmadığını bilir.
senkronizasyon_fence
sync_fence
genellikle farklı sync_timeline
üst öğelerine (ekran denetleyicisi ve GPU için olduğu gibi) sahip olan bir sync_pt
değerleri koleksiyonudur. sync_fence
, sync_pt
ve sync_timeline
, sürücülerin ve kullanıcı alanının bağımlılıklarını iletmek için kullandığı ana temel öğelerdir. Bir çit sinyali verildiğinde, çekirdek sürücüsü veya donanım bloğu komutları sırayla yürüttüğü için çitten önce verilen tüm komutların tamamlanması garanti edilir.
Senkronizasyon çerçevesi, birden fazla tüketicinin veya üreticinin işleri bittiğinde bir arabellek kullanarak sinyal göndermesine olanak tanır ve bağımlılık bilgilerini tek bir işlev parametresi ile iletir. Çitler bir dosya tanımlayıcı tarafından desteklenir ve çekirdek alanından kullanıcı alanına aktarılır. Örneğin bir çit, iki ayrı görüntü tüketicisinin arabelleği okumayı bitirdiğini belirten iki sync_pt
değeri içerebilir. Çit sinyali verildiğinde görüntü üreticileri her iki tüketicinin de tüketmeyi bıraktığını bilir.
Çitler, tıpkı sync_pt
değerleri gibi, aktif olarak başlar ve noktalarının durumuna göre durum değiştirir. Tüm sync_pt
değerleri sinyallenirse, sync_fence
sinyallenir. Bir sync_pt
hata durumuna düşerse tüm sync_fence
bir hata durumu olur.
sync_fence
üyeliği, çit oluşturulduktan sonra değiştirilemez. Bir çitte birden fazla nokta elde etmek için, iki farklı çitin noktalarının üçüncü bir çite eklendiği bir birleştirme yapılır. Bu noktalardan biri başlangıç çitinde sinyal verilmişse ve diğeri değilse, üçüncü çit de sinyal verilmiş durumda olmayacaktır.
Açık senkronizasyonu uygulamak için aşağıdakileri sağlayın:
- Belirli bir donanım sürücüsü için senkronizasyon çerçevesini uygulayan bir çekirdek alanı alt sistemi. Çite duyarlı olması gereken sürücüler genellikle Donanım Oluşturucuya erişen veya onunla iletişim kuran herhangi bir şeydir. Anahtar dosyalar şunları içerir:
- Çekirdek uygulama:
-
kernel/common/include/linux/sync.h
-
kernel/common/drivers/base/sync.c
-
-
kernel/common/Documentation/sync.txt
adresindeki belgeler -
platform/system/core/libsync
çekirdek alanıyla iletişim kuracak kitaplık
- Çekirdek uygulama:
- Satıcı, HAL'deki
validateDisplay()
vepresentDisplay()
işlevlerine parametre olarak uygun senkronizasyon çitlerini sağlamalıdır. - Çitle ilgili iki GL uzantısı (
EGL_ANDROID_native_fence_sync
veEGL_ANDROID_wait_sync
) ve grafik sürücüsünde çit desteği.
Örnek olay: Bir ekran sürücüsünü uygulama
Senkronizasyon işlevini destekleyen API'yi kullanmak için, ekran arabelleği işlevine sahip bir ekran sürücüsü geliştirin. Senkronizasyon çerçevesi mevcut olmadan önce bu işlev, dma-buf
nesnelerini alır, bu arabellekleri ekrana yerleştirir ve arabellek görünür durumdayken bloke ederdi. Örneğin:
/* * assumes buffer is ready to be displayed. returns when buffer is no longer on * screen. */ void display_buffer(struct dma_buf *buffer);
Senkronizasyon çerçevesiyle display_buffer
işlevi daha karmaşıktır. Bir tamponu ekrana koyarken, tampon, tamponun ne zaman hazır olacağını belirten bir çitle ilişkilendirilir. Çit temizlendikten sonra sıraya girip çalışmaya başlayabilirsiniz.
Çit temizlendikten sonra sıraya girmek ve işi başlatmak hiçbir şeyi engellemez. Tamponun ne zaman ekrandan çıkacağını garanti eden kendi çitinizi hemen geri getirirsiniz. Siz arabellekleri sıraya koyarken çekirdek, senkronizasyon çerçevesiyle olan bağımlılıkları listeler:
/* * displays buffer when fence is signaled. returns immediately with a fence * that signals when buffer is no longer displayed. */ struct sync_fence* display_buffer(struct dma_buf *buffer, struct sync_fence *fence);
Senkronizasyon entegrasyonu
Bu bölümde, çekirdek alanı senkronizasyon çerçevesinin, Android çerçevesinin kullanıcı alanı bölümleriyle ve birbirleriyle iletişim kurması gereken sürücülerle nasıl entegre edileceği açıklanmaktadır. Çekirdek alanı nesneleri, kullanıcı alanında dosya tanımlayıcıları olarak temsil edilir.
Entegrasyon kuralları
Android HAL arayüz kurallarına uyun:
- API,
sync_pt
başvuran bir dosya tanımlayıcı sağlıyorsa, satıcının sürücüsünün veya API'yi kullanan HAL'nin dosya tanımlayıcıyı kapatması gerekir. - Satıcı sürücüsü veya HAL, bir API işlevine
sync_pt
içeren bir dosya tanımlayıcıyı geçirirse, satıcı sürücüsü veya HAL, dosya tanımlayıcıyı kapatmamalıdır. - Koruma dosyası tanımlayıcısını kullanmaya devam etmek için satıcı sürücüsünün veya HAL'nin tanımlayıcıyı çoğaltması gerekir.
Bir çit nesnesi BufferQueue'dan her geçtiğinde yeniden adlandırılır. Çekirdek çit desteği, çitlerin adlar için dizelere sahip olmasına izin verir, bu nedenle senkronizasyon çerçevesi, çiti adlandırmak için sıraya alınan pencere adını ve arabellek dizinini kullanır; örneğin SurfaceView:0
. Bu, adların /d/sync
çıktısında ve hata raporlarında görünmesi nedeniyle, kilitlenmenin kaynağını tanımlamak için hata ayıklamada faydalıdır.
ANativeWindow entegrasyonu
ANativeWindow çit farkındadır. dequeueBuffer
, queueBuffer
ve cancelBuffer
koruma parametrelerine sahiptir.
OpenGL ES entegrasyonu
OpenGL ES senkronizasyon entegrasyonu iki EGL uzantısına dayanır:
-
EGL_ANDROID_native_fence_sync
EGLSyncKHR
nesnelerinde yerel Android çit dosyası tanımlayıcılarını sarmak veya oluşturmak için bir yol sağlar. -
EGL_ANDROID_wait_sync
, CPU tarafı yerine GPU tarafının durmasına izin vererek GPU'nunEGLSyncKHR
beklemesini sağlar.EGL_ANDROID_wait_sync
uzantısı,EGL_KHR_wait_sync
uzantısıyla aynıdır.
Bu uzantıları bağımsız olarak kullanmak için, ilgili çekirdek desteğiyle birlikte EGL_ANDROID_native_fence_sync
uzantısını uygulayın. Daha sonra sürücünüzde EGL_ANDROID_wait_sync
uzantısını etkinleştirin. EGL_ANDROID_native_fence_sync
uzantısı, farklı bir yerel çit EGLSyncKHR
nesne türünden oluşur. Sonuç olarak, mevcut EGLSyncKHR
nesne türleri için geçerli olan uzantıların EGL_ANDROID_native_fence
nesneleri için de geçerli olması gerekmeyebilir ve bu da istenmeyen etkileşimlerin önüne geçer.
EGL_ANDROID_native_fence_sync
uzantısı, yalnızca oluşturma sırasında ayarlanabilen ve mevcut bir senkronizasyon nesnesinden ileriye doğru doğrudan sorgulanamayan, karşılık gelen bir yerel çit dosyası tanımlayıcı özelliğini kullanır. Bu özellik iki moddan birine ayarlanabilir:
- Geçerli bir çit dosyası tanımlayıcısı, mevcut bir yerel Android çit dosyası tanımlayıcısını bir
EGLSyncKHR
nesnesine sarar. - -1, bir
EGLSyncKHR
nesnesinden yerel bir Android çit dosyası tanımlayıcısı oluşturur.
EGLSyncKHR
nesnesini yerel Android çit dosyası tanımlayıcısından çıkarmak için DupNativeFenceFD()
işlev çağrısını kullanın. Bu, set özniteliğinin sorgulanmasıyla aynı sonucu verir, ancak alıcının çiti kapatması kuralına uyar (dolayısıyla çoğaltma işlemi). Son olarak EGLSyncKHR
nesnesinin yok edilmesi dahili çit özelliğini kapatır.
Donanım Oluşturucu entegrasyonu
Donanım Oluşturucusu üç tür senkronizasyon çitini yönetir:
- Alma çitleri, giriş arabellekleriyle birlikte
setLayerBuffer
vesetClientTarget
çağrılarına iletilir. Bunlar, arabelleğe bekleyen bir yazmayı temsil eder ve SurfaceFlinger veya HWC, kompozisyonu gerçekleştirmek için ilgili arabellekten okumaya çalışmadan önce sinyal vermelidir. - Serbest bırakma çitleri,
getReleaseFences
çağrısını kullanarakpresentDisplay
çağrısından sonra alınır. Bunlar, aynı katmandaki önceki arabellekten bekleyen bir okumayı temsil eder. Geçerli arabellek ekrandaki önceki arabelleğin yerini aldığı için HWC artık önceki arabelleği kullanmadığında, serbest bırakma çiti sinyali verir. Serbest bırakma çitleri, geçerli kompozisyon sırasında değiştirilecek olan önceki arabelleklerle birlikte uygulamaya geri aktarılır. Uygulamanın, kendisine döndürülen ara belleğe yeni içerik yazmadan önce serbest bırakma sinyali verene kadar beklemesi gerekir. -
presentDisplay
çağrısının bir parçası olarak mevcut çitler , kare başına bir tane olmak üzere döndürülür. Mevcut çitler, bu çerçevenin kompozisyonunun ne zaman tamamlandığını veya alternatif olarak önceki çerçevenin kompozisyon sonucuna artık ihtiyaç duyulmadığı zamanı temsil eder. Fiziksel ekranlar için,presentDisplay
geçerli çerçeve ekranda göründüğünde mevcut çerçeveleri döndürür. Mevcut çitler döndürüldükten sonra, mümkünse SurfaceFlinger hedef arabelleğine yeniden yazmak güvenlidir. Sanal ekranlar için, çıkış arabelleğinden okumak güvenli olduğunda mevcut çitler döndürülür.