Senkronizasyon Çerçevesi

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ı göstermesini sağlayan bir API sağlar. Çerçeve ayrıca senkronizasyon ilkelerinin çekirdekten kullanıcı alanına sürücüler arasında ve kullanıcı alanı süreçleri arasında aktarılmasına da izin verir.

Örneğin, bir uygulama GPU'da gerçekleştirilecek işi sıraya alabilir. GPU bu görüntüyü çizmeye başlar. Görüntü henüz belleğe çekilmemiş olsa da arabellek işaretçisi, GPU çalışmasının ne zaman biteceğini gösteren bir çitle birlikte pencere oluşturucusuna iletilir. Pencere oluşturucu önceden işlemeye başlar ve işi ekran denetleyicisine aktarır. Benzer şekilde, CPU çalışması vaktinden önce yapılır. GPU bittiğinde, ekran denetleyicisi görüntüyü hemen görüntüler.

Senkronizasyon çerçevesi, 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 hattına görünürlük sağlar.

Açık senkronizasyon

Açık senkronizasyon, grafik arabelleği üreticilerinin ve tüketicilerinin arabelleği kullanmayı bitirdiklerinde sinyal vermelerini sağlar. Açık senkronizasyon, çekirdek uzayında gerçekleştirilir.

Açık senkronizasyonun faydaları şunları içerir:

  • Cihazlar arasında daha az davranış varyasyonu
  • Daha iyi hata ayıklama desteği
  • Geliştirilmiş test ölçümleri

Eşitleme çerçevesinin üç nesne türü vardır:

  • sync_timeline
  • sync_pt
  • sync_fence

sync_timeline

sync_timeline , satıcıların GL bağlamı, görüntü denetleyicisi veya 2D blitter 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ü uygulamaları etkinleştirir.

sync_timeline uygularken şu yönergeleri izleyin:

  • Hata ayıklamayı basitleştirmek için tüm sürücüler, zaman çizelgeleri ve sınırlamalar için yararlı adlar sağlayın.
  • Hata ayıklama çıktısını daha okunaklı hale getirmek için timeline_value_str ve pt_value_str operatörlerini timeline'larda uygulayın.
  • GL kitaplığı gibi kullanıcı alanı kitaplıklarına, istenirse özel zaman çizelgesi verilerine erişim sağlamak için dolgu driver_data uygulayın. data_driver satıcıların değiştirilemez sync_fence ve sync_pts hakkında bilgi sync_fence ve sync_pts dayalı komut satırları oluşturması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 / sınırlar oluşturmak, boru hattı işlevselliğini durduran bir hizmet reddi saldırısıyla sonuçlanır.
  • sync_timeline , sync_pt veya sync_fence öğelerine açıkça sync_fence . API, gerekli tüm işlevleri sağlar.

sync_pt

sync_pt bir tek değeri veya bir yer sync_timeline . Bir noktanın üç durumu vardır: etkin, işaretli ve hata. Noktalar aktif durumda başlar ve sinyal veya hata durumlarına geçiş yapar. Örneğin, bir görüntü tüketicisi artık bir arabelleğe ihtiyaç sync_pt , bir sync_pt sinyali gönderilir, böylece bir görüntü üreticisi arabelleğe tekrar yazmanın uygun olduğunu bilir.

sync_fence

sync_fence , genellikle farklı sync_timeline (ekran denetleyicisi ve GPU için olduğu gibi) sahip olan sync_pt değerlerinin bir koleksiyonudur. sync_fence , sync_pt ve sync_timeline , sürücülerin ve kullanıcı sync_timeline bağımlılıklarını iletmek için kullandıkları ana ilkeldir. Bir çit sinyallendiğinde, perdeden önce verilen tüm komutların tamamlanması garanti edilir çünkü çekirdek sürücüsü veya donanım bloğu komutları sırayla yürütür.

Senkronizasyon çerçevesi, birden fazla tüketicinin veya üreticinin, bağımlılık bilgilerini bir işlev parametresiyle ileterek, bir arabellek kullanarak işlerini bitirdiğinde sinyal vermesine olanak tanır. Ç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 bir arabelleği okumayı bitirdiğini belirten iki sync_pt değeri içerebilir. Çit sinyal verildiğinde, görüntü üreticileri her iki tüketicinin de tüketmeyi bitirdiğini bilir.

sync_pt değerleri gibi sync_pt aktif olarak başlar ve noktalarının durumuna göre durumu değiştirir. Tüm sync_pt değerleri sinyallenirse, sync_fence sinyallenir. Bir sync_pt bir hata durumuna düşerse, tüm sync_fence bir hata durumuna sahiptir.

Bir sync_fence üyeliği çit oluşturulduktan sonra değişmez. Bir çitte birden fazla nokta elde etmek için, iki farklı çite ait noktaların üçüncü bir çite eklendiği bir birleştirme yapılır. Bu noktalardan biri başlangıç ​​çitinde sinyal verildiyse ve diğeri değilse, üçüncü çit de sinyal verilmiş durumda olmayacaktır.

Açık senkronizasyon 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. Çitlere duyarlı olması gereken sürücüler genellikle Donanım Oluşturucu'ya erişen veya onunla iletişim kuran herhangi bir şeydir. Anahtar dosyalar şunları içerir:
    • Temel uygulama:
      • kernel/common/include/linux/sync.h
      • kernel/common/drivers/base/sync.c
    • kernel/common/Documentation/sync.txt
    • platform/system/core/libsync çekirdek alanıyla iletişim kurmak için platform/system/core/libsync
  • Satıcı, presentDisplay() validateDisplay() ve presentDisplay() işlevlerine parametre olarak uygun senkronizasyon çitlerini sağlamalıdır.
  • İki çitle ilgili GL uzantısı ( EGL_ANDROID_native_fence_sync ve EGL_ANDROID_wait_sync ) ve grafik sürücüsünde çit desteği.

Örnek olay incelemesi: Bir ekran sürücüsü uygulama

Senkronizasyon işlevini destekleyen API'yi kullanmak için, ekran arabelleği işlevi olan bir ekran sürücüsü geliştirin. Senkronizasyon çerçevesi mevcut olmadan önce, bu işlev dma-buf nesnelerini alır, bu tamponları ekrana koyar ve tampon 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çevesi ile display_buffer işlevi daha karmaşıktır. Ekrana bir arabellek koyarken, arabellek arabelleğin ne zaman hazır olacağını gösteren bir perdeyle ilişkilendirilir. Çit temizlendikten sonra sıraya girebilir ve işi başlatabilirsiniz.

Çit temizlendikten sonra sıraya koymak ve işi başlatmak hiçbir şeyi engellemez. Arabelleğin ekrandan ne zaman çıkacağını garanti eden kendi çitinizi hemen iade edersiniz. Arabellekleri sıraya koyduğunuzda, çekirdek, senkronizasyon çerçevesiyle 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üm, çekirdek alanı eşitleme çerçevesinin Android çerçevesinin kullanıcı alanı bölümleriyle ve birbiriyle iletişim kurması gereken sürücülerle nasıl entegre edileceğini açıklar. Çekirdek uzay nesneleri, kullanıcı alanında dosya tanımlayıcıları olarak temsil edilir.

Entegrasyon kuralları

Android HAL arayüz kurallarını takip edin:

  • API, bir sync_pt bir dosya tanımlayıcı sync_pt , satıcının sürücüsü veya API'yi kullanan HAL, dosya tanımlayıcısını kapatmalıdır.
  • Satıcı sürücüsü veya HAL, bir API işlevine sync_pt içeren bir dosya tanımlayıcısını sync_pt , satıcı sürücüsü veya HAL dosya tanımlayıcısını kapatmamalıdır.
  • Perdeleme dosya tanımlayıcısını kullanmaya devam etmek için, satıcı sürücüsü veya HAL tanımlayıcıyı çoğaltmalıdır.

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, SurfaceView:0 gibi çiti adlandırmak için sıraya alınan pencere adını ve tampon dizinini kullanır. Bu, adlar /d/sync çıktısında ve hata raporlarında göründükçe bir kilitlenmenin kaynağını belirlemek için hata ayıklamada yararlıdır.

ANativeWindow entegrasyonu

ANativeWindow çit farkındadır. dequeueBuffer , queueBuffer ve cancelBuffer çit 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 dosya tanımlayıcılarını sarmak veya oluşturmak için bir yol sağlar.
  • EGL_ANDROID_wait_sync GPU tarafı için GPU beklemek yapma yerine CPU tarafı daha durdurulmasıdır verir EGLSyncKHR . EGL_ANDROID_wait_sync uzantısı ile aynıdır EGL_KHR_wait_sync uzantısı.

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. Ardından, 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 EGL_ANDROID_native_fence , istenmeyen etkileşimlerden kaçınarak EGL_ANDROID_native_fence nesnelerine mutlaka uygulanmaz.

EGL_ANDROID_native_fence_sync uzantısı, yalnızca oluşturma sırasında ayarlanabilen ve doğrudan mevcut bir senkronizasyon nesnesinden ileriye doğru sorgulanamayan karşılık gelen bir yerel çit dosyası tanımlayıcı özniteliği 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 EGLSyncKHR .
  • -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ğini sorgulamakla aynı sonuca sahiptir, ancak alıcının perdeyi kapatması kuralına (dolayısıyla yinelenen işlem) bağlıdır. Son olarak, EGLSyncKHR nesnesinin yok edilmesi, dahili çit niteliğini kapatır.

Donanım Besteci entegrasyonu

Hardware Composer, üç tür senkronizasyon sınırını yönetir:

  • Edinme sınırları , giriş arabellekleriyle birlikte setLayerBuffer ve setClientTarget çağrılarına setClientTarget . Bunlar, arabelleğe beklemede olan bir yazmayı temsil eder ve SurfaceFlinger veya HWC, kompozisyonu gerçekleştirmek için ilişkili arabellekten okumaya çalışmadan önce sinyal vermelidir.
  • Serbest bırakma çitleri , getReleaseFences çağrısı kullanılarak presentDisplay çağrısından sonra alınır. Bunlar, aynı katmandaki önceki tampondan bekleyen okumayı temsil eder. Bir serbest bırakma perdesi, HWC artık önceki arabelleği kullanmadığında sinyal verir, çünkü geçerli ara bellek, ekrandaki önceki arabelleğin yerini almıştır. Serbest bırakma çitleri, mevcut kompozisyon sırasında değiştirilecek önceki tamponlarla birlikte uygulamaya geri aktarılır. Uygulama, geri gönderilen arabelleğe yeni içerikler yazmadan önce bir yayın çitinin sinyal vermesini beklemelidir.
  • presentDisplay çağrısının bir parçası olarak mevcut çitler çerçeve başına bir tane 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ığında temsil eder. Fiziksel görüntüler için, presentDisplay geçerli çerçeve ekranda göründüğünde mevcut çitleri döndürür. Mevcut çitler iade edildikten sonra, uygulanabilirse SurfaceFlinger hedef arabelleğine yeniden yazmak güvenlidir. Sanal ekranlar için, çıktı arabelleğinden okunması güvenli olduğunda mevcut çitler döndürülür.