Powrót do strony głównej

Rozszerzenia OpenGL w PHP FFI przez GLFW

Artykuł opisuje implementację rozszerzeń OpenGL w PHP FFI przez GLFW bez zewnętrznych DLL. Zautomatyzowana generacja mostków z nagłówków C, proceduralne atrapy zapewniają autouzupełnianie. Pełna wieloplatformowość z glfwGetProcAddress.

PHP FFI + GLFW: dynamiczne rozszerzenia OpenGL
Advertisement 728x90

Dynamiczne ładowanie OpenGL przez GLFW w PHP FFI

W podejściu PHP FFI do OpenGL ręczne kopiowanie stałych i typedef z nagłówków GLFW3 prowadzi do nadmiarowego kodu szablonowego. Konwertujemy #define na stałe PHP i wstawiamy funkcje API do sekcji zasobów bez zmian.

Przykład transformacji:

// glfw3.h
#define GLFW_VERSION_MAJOR 3

// glfw3.php
const GLFW_VERSION_MAJOR = 3;
// glfw3.h
GLFWAPI void glfwMakeContextCurrent(GLFWwindow* window);

// glfw3.php (w __halt_compiler())
void glfwMakeContextCurrent(GLFWwindow* window);

Funkcje FFI zachowują się jak metody obiektu proxy i wskaźniki jednocześnie:

Google AdInline article slot
$glfwMakeContextCurrent = $glfw->glfwMakeContextCurrent;
$glfwMakeContextCurrent($window);

Proceduralne nakładki dla autouzupełniania

Tworzymy funkcje PHP-opakowania ze statycznym buforowaniem wskaźników dla typowania i wsparcia IDE:

const GLFW_INSTANCE = FFI::cdef(...);

function glfwMakeContextCurrent(mixed ...$args): void {
    static $function = GLFW_INSTANCE->glfwMakeContextCurrent;
    $function(...$args);
}

To podejście minimalizuje wywołania metod FFI-proxy, zastępując je domknięciami. Wydajność jest zachowana, ponieważ adresy funkcji są statyczne.

Alternatywy (niezalecane):

Google AdInline article slot
  • Przekazywanie $glfw jako pierwszego argumentu.
  • global $glfw.

Z stałą GLFW_INSTANCE główny kod upraszcza się:

require 'src/glfw3.php';

if (!glfwInit()) exit(-1);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
$window = glfwCreateWindow(640, 480, 'Hello World', null, null);

Dynamiczne ładowanie OpenGL bez opengl32.dll

Funkcje OpenGL są ładowane dynamicznie przez zależne od platformy funkcje GetProcAddress:

  • Windows: wglGetProcAddress
  • Linux: glXGetProcAddressARB
  • Android: eglGetProcAddress

GLFW ujednolica to w wieloplatformową glfwGetProcAddress:

Google AdInline article slot
function glClear(mixed ...$args): void {
    static $function = GLFW_INSTANCE->cast(
        'PFNGLCLEARPROC',
        GLFW_INSTANCE->glfwGetProcAddress('glClear')
    );
    $function(...$args);
}

Typy takie jak PFNGLCLEARPROC są pobierane z glcorearb.h:

typedef void (*PFNGLCLEARPROC)(GLbitfield mask);

Wsparcie rozszerzeń (NV, AMD → ARB) jest sprawdzane dynamicznie: sprzęt określa dostępne funkcje, sterowniki emulują brakujące.

Generowanie mostów ze źródeł

Automatyzujemy tworzenie glfw3.php (20k+ linii):

  • ffi/preprocessor: przekształca nagłówki C w format PHP, wyodrębnia definicje.
  • ffi/ide-helper-generator: generuje nakładki z typami argumentów.

Wybrano GLFW 3.3 dla kompatybilności z Ubuntu 24.04. Stałe i funkcje OpenGL są zintegrowane w jeden plik, opengl.php został usunięty.

Zalety:

  • Pełna kompatybilność z ext-glfw.
  • Wieloplatformowość bez ręcznego dostosowywania.
  • Autouzupełnianie i typowanie bez kompilacji.

Co jest ważne

  • GLFW_INSTANCE jako globalna stała zapewnia szybki dostęp do FFI bez zmiennych globalnych.
  • Typy *PFNGLPROC** z glcorearb.h upraszczają rzutowanie bez ręcznego określania sygnatur.
  • glfwGetProcAddress zastępuje platformowy zbiór (WGL/GLX/EGL).
  • Generowanie ze źródeł gwarantuje aktualność 20k+ linii.
  • Wydajność: statyczna pamięć podręczna minimalizuje narzut metod FFI.

Kod jest gotowy do rysowania trójkątów z buforami i shaderami w następnej części.

— Editorial Team

Advertisement 728x90

Czytaj dalej