Wtyczka do przeglądarki dla Unity

Narzędzia programistyczne i silnik Unity to zdecydowanie najpopularniejszy obecnie sposób tworzenia aplikacji VR i AR. Już wcześniej umożliwiliśmy eksportowanie z Unity doświadczeń opartych na przeglądarce internetowej. Dziś jesteśmy podekscytowani, że możemy pokazać wczesne prace nad innym sposobem, w jaki programiści Unity chcą korzystać z sieci: jako komponentu w swoich wirtualnych środowiskach opartych na Unity.

Budując na podstawie naszej pracy nad przeniesieniem silnika przeglądarki na wiele platform i scenariuszy osadzania, w tym jako Firefox Reality AR dla HoloLens 2, zbudowaliśmy nowy komponent Unity oparty na Servo, nowoczesnym silniku sieciowym napisanym w języku Rust.

Silnik Unity ma bardzo elastyczny, wieloplatformowy system wtyczek ze zdrowym ekosystemem wtyczek innych firm, zarówno open-source, jak i własnościowych. System wtyczek pozwala nam na uruchamianie modułów natywnych dla systemu operacyjnego i podłączanie ich bezpośrednio do komponentów wykonywanych w środowisku skryptowym Unity.

Celem eksperymentów było zbudowanie natywnej wtyczki Unity i zestawu komponentów skryptowych Unity C#, które pozwoliłyby stronom trzecim na włączenie okien przeglądarki Servo do scen Unity, a opcjonalnie zapewniłyby obsługę korzystania z powierzchni przeglądarki w aplikacjach VR i AR zbudowanych w Unity.

Dzisiaj udostępniamy w pełni funkcjonalny prototyp przeglądarki Servo działający wewnątrz wtyczki Unity. Jest to wczesny etap naszej pracy, ale wiemy, że tego typu rozwiązanie wzbudza duże zainteresowanie, więc mamy nadzieję, że wypróbujecie ten prototyp, przekażecie swoje opinie i dołączycie do nas w budowaniu rzeczy za jego pomocą. Wydana dziś wersja jest przeznaczona na platformę macOS, ale wkrótce dodamy kilka innych platform obsługiwanych przez Servo.

Zaczynamy

Otworzyliśmy wtyczkę na zasadach open-sourcowych pod adresem https://github.com/MozillaReality/servo-unity. Udaj się tam, kliknij gwiazdkę i rozwidl kod, sprawdź go na swojej lokalnej maszynie, a następnie otwórz projekt w Unity.

Instrukcje dla programistów znajdują się w pliku README w repozytorium.

Co to robi

Możesz pracować bezpośrednio z oknem przeglądarki i kontrolkami wewnątrz edytora Unity. Konfiguracja najwyższego poziomu znajduje się na obiekcie ServoUnityController. Inne ważne obiekty w scenie to ServoUnityWindow, ServoUnityNavbarController i ServoUnityMousePointer.

Obiekt ServoUnityWindow może być umieszczony w dowolnym miejscu w scenie Unity. Tutaj umieściliśmy go w jaskini grzybów Mozilli (znanej użytkownikom Firefox Reality, autorstwa niesamowitej artystki Jasmin Habezai-Fekri) i wyposażyliśmy w manipulator kamery, który pozwala nam poruszać się po scenie i zobaczyć, że jest to trójwymiarowy widok zawartości przeglądarki.

Servo ma możliwość odtwarzania wysokiej jakości multimediów za pomocą frameworka GStreamer, w tym obsługi dźwięku. Tutaj oglądamy przykładowe wideo MPEG4, działające wewnątrz wdrożonego odtwarzacza Unity.

Wtyczka zawiera konfigurowalne wyszukiwanie. W obecnej wersji Servo można przeglądać szeroką gamę treści internetowych, przy czym trwają intensywne prace nad zwiększeniem kompatybilności z siecią (więcej na ten temat poniżej). Zawartość WebGL również działa.

Jak to działa

Architektura

Rozwój w Unity wykorzystuje architekturę opartą na komponentach, gdzie Unity wykonuje kod użytkownika dołączony do GameObjects, zorganizowanych w sceny. Użytkownicy dostosowują GameObjects poprzez dołączanie skryptów, które wykonują się w środowisku C#, używając runtime Mono lub kompilatora IL2CPP ahead-of-time. Cykl życia zdarzeń Unity jest dostępny dla skryptów użytkownika dziedziczących po klasie Unity C# MonoBehaviour. Skrypty użytkownika mogą wywoływać natywny kod we wtyczkach (które są po prostu dynamicznymi obiektami współdzielonymi systemu operacyjnego) za pomocą mechanizmu P/Invoke trybu runtime C#. W rzeczywistości sam rdzeń Unity jest zaimplementowany w C++ i zapewnia natywnemu kodowi we wtyczkach drugi zestaw interfejsów dostępnych dla C/C++, aby pomóc w niektórych niskopoziomowych zadaniach wtyczek.

Servo jest samo w sobie złożonym oprogramowaniem. Z założenia większość jego funkcjonalności, która nie jest skierowana do użytkownika, jest skompilowana do biblioteki Rust, libservo. W tej pierwszej fazie projektu korzystamy z uproszczonego interfejsu kompatybilnego z językiem C w innej bibliotece Rust o nazwie libsimpleservo2. Biblioteka ta udostępnia funkcje wywoływane w języku C oraz haki wywołań zwrotnych do sterowania przeglądarką i wyświetlania jej danych wyjściowych. Wokół libsimpleservo2 umieściliśmy natywne abstrakcje C++, które hermetyzują model Unity dotyczący wątków i renderowania, a także udostępniają wywoływalny przez Unity zestaw interfejsów, które są z kolei obsługiwane przez nasze komponenty skryptowe C#.

Wprowadzanie zawartości przeglądarki do Unity

Tworzymy obiekt w Unity, instancję ServoUnityWindow, aby zawinąć instancję klasy Unity Texture2D i traktować ją jako panel zawartości przeglądarki. Gdy używamy renderera OpenGL w Unity, klasa Texture2D jest wspierana przez natywną teksturę OpenGL, a my przekazujemy „nazwę” tekstury OpenGL (tj. identyfikator) do wtyczki, która wiąże teksturę z obiektem bufora ramki, który otrzymuje ostateczną skomponowaną teksturę z Servo.

Ponieważ nie mamy kontroli nad wiązaniem tekstury i kontekstu Unity, obecny projekt aktualizacji tej tekstury wykorzystuje blit (kopię) za pośrednictwem surfman-chains API Servo. Zasadniczo, WebRender Servo zapisuje do specyficznego dla systemu operacyjnego bufora powierzchniowego w jednym wątku, a następnie ten bufor powierzchniowy jest powiązany tylko do odczytu z wątkiem renderowania Unity i kopia tekstury jest wykonywana przy użyciu interfejsów API OpenGL. W początkowej implementacji macOS na przykład, bufor powierzchniowy jest IOSurface, który może być bezkosztowo przenoszony między wątkami, umożliwiając wydajną implementację, w której kompozytor przeglądarki może pisać w innym wątku niż wątek wyświetlający teksturę w Unity.

Kontrola i meta-dane strony są przekazywane oddzielnie, za pośrednictwem zestawu interfejsów API, które umożliwiają wyszukiwanie i nawigację do adresów URL, aktualizację tytułów stron i zwykły zestaw przycisków wstecz/do przodu/stop/home.

Ponieważ zawartość przeglądarki i elementy sterujące są ostatecznie obiektami Unity, budowana aplikacja Unity może je pozycjonować, stylizować lub programowo kontrolować w dowolny sposób.

Wyzwania

Doprowadzenie projektu do tego etapu nie obyło się bez wyzwań, z których część wciąż rozwiązujemy. Środowisko skryptowe Unity działa w dużej mierze jednowątkowo, z wyjątkiem operacji renderowania, które odbywają się na osobnym wątku w innej kadencji. Servo natomiast tworzy potencjalnie dziesiątki lekkich wątków do różnych zadań. Zadbaliśmy o to, aby elementy robocze powracające z Servo były kierowane do odpowiednich wątków w Unity. Pozostało jeszcze kilka optymalizacji w decydowaniu o tym, kiedy odświeżyć teksturę Unity. Obecnie odświeżana jest ona co klatkę, ale dodajemy API do interfejsu osadzania, aby umożliwić bardziej szczegółową kontrolę.

Jako inkubator technologii przeglądarkowych, Servo koncentruje się na rozwijaniu nowych technologii. Godne uwagi rozwiązania techniczne, które przeszły z Servo do silnika Gecko napędzającego Firefoksa, obejmują oparty na GPU silnik renderujący WebRender oraz silnik CSS Stylo. Pomijając te sukcesy, pełna kompatybilność sieciowa to wciąż obszar, w którym Servo ma spore braki, ponieważ skupiliśmy się przede wszystkim na dużych usprawnieniach dla użytkowników i specyficznych doświadczeniach w długim ogonie sieci. Niedawny wysiłek społeczności Servo zaowocował ogromnym postępem w zakresie webcompat Servo, więc spodziewamy się, że podzbiór sieci przeglądanych przez Servo będzie nadal szybko się powiększał.

Plany rozwoju

Obsługa pełnego zakresu platform obsługiwanych obecnie przez Servo jest naszym pierwszym priorytetem, z obsługą Windows Win32 i Windows UWP na szczycie listy. Wielu z Was widziało naszą aplikację Firefox Reality AR for HoloLens 2, a obsługa UWP pozwoli Wam wbudować Servo w Wasze własne aplikacje AR na platformę HoloLens, wykorzystując ten sam bazowy silnik przeglądarki.

Chcielibyśmy również wspierać większy podzbiór pełnych możliwości przeglądarki. Na szczycie listy znajduje się obsługa wielu okien. Obecnie pracujemy nad przeniesieniem wtyczki z interfejsu libsimpleservo2 do nowego interfejsu, który pozwoli aplikacjom na tworzenie wielu okien, zakładek i implementację funkcji takich jak historia, zakładki i wiele innych.

To pierwsze wydanie koncentruje się na przeglądaniu stron internetowych 2D. Servo obsługuje również wciągającą sieć za pośrednictwem interfejsu API WebXR i badamy możliwość połączenia WebXR z obsługą sprzętu XR w Unity za pośrednictwem interfejsu wtyczek. Zaczniemy od obsługi wideo 360°, które – jak wiemy z bazy użytkowników Firefox Reality – jest głównym zastosowaniem przeglądarki.

Wreszcie…

Czy to odtwarzacz multimedialny, interfejs w grze do otwartej sieci, przeglądarka jako interfejs użytkownika, wprowadzanie specyficznych doświadczeń sieciowych, czy też niezliczona liczba innych możliwości, nie możemy się doczekać, aby zobaczyć, w jaki sposób programiści wykorzystają moc i wydajność Servo w aplikacjach stworzonych w Unity.