Files
lazopenglcontextex/README.md
T
ew8bakandClaude Fable 5 ac46e3d13a LazOpenGLContextEx: TOpenGLControl с Qt-бэкендом на QOpenGLWidget
Форк штатного пакета LazOpenGLContext (Lazarus components/opengl).
Qt5/Qt6-бэкенд (glqtnativecontext.pas) использует собственный контекст
настоящего QOpenGLWidget вместо ручного GLX на winId(): EGL на Wayland,
GLX на X11, WGL/CGL на Windows/macOS под ws=qt6.

QOpenGLWidget-наследник с paintGL-хуком живёт в маленькой C++-либе
csrc/qlclglwidget.cpp (QLCLOpenGLWidget из libQt6Pas — не QOpenGLWidget,
а голый QWidget под внешний GLX). Сборка: csrc/Makefile
(linux/macos/windows-кросс mingw-w64/windows-native MSYS2, install,
install-app) + build-msvc.bat для MSVC-Qt. Либа грузится в рантайме
рядом с бинарником приложения.

Бэкенды gtk2/gtk3/win32/cocoa скопированы из стока без изменений
(юниты переименованы с суффиксом Ex). Детали и нюансы — в README.md.

Проверено: EWSDR, спектр/водопад через GL в нативном Wayland (KDE, qt6),
живой эфир QO-100.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 15:00:26 +03:00

111 lines
7.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# LazOpenGLContextEx
Форк штатного пакета `LazOpenGLContext` (Lazarus `components/opengl`), в котором
Qt5/Qt6-бэкенд построен на настоящем `QOpenGLWidget` вместо GLX.
## Зачем
Штатный `TOpenGLControl` под `--ws=qt5/qt6` работает только в X11-сессии и
вообще не собирается с Qt-виджетсетом на Windows/macOS: он руками создаёт
GLX-контекст на `winId()`. Важно: `QLCLOpenGLWidget` из libQt6Pas — это **не**
QOpenGLWidget, а голый QWidget с `WA_NativeWindow` и `paintEngine()=nullptr`,
т.е. просто мишень для внешнего GLX-рендера (вызов на нём методов
QOpenGLWidget = access violation — проверено).
Здесь контекст создаёт сам Qt через платформенный API:
| Платформа | Контекст |
|------------------|----------|
| Linux Wayland | EGL |
| Linux X11 | GLX |
| Windows (ws=qt6) | WGL |
| macOS (ws=qt6) | CGL |
Бэкенды gtk2/gtk3/win32/cocoa скопированы из штатного пакета без изменений
(юниты переименованы с суффиксом `Ex`, чтобы не конфликтовать со стоковым пакетом).
## Состав
- `openglcontextex.pas``TOpenGLControl` (класс называется так же, юнит `OpenGLContextEx`).
- `glqtnativecontext.pas` — Qt-бэкенд поверх QOpenGLWidget.
- `csrc/qlclglwidget.cpp`**вспомогательная C++-библиотека** `libqlclglwidget.so`:
наследник QOpenGLWidget с paintGL-хуком в Pascal + плоские экспорты
(`makeCurrent`, `doneCurrent`, `isValid`, `setFormat`,
`defaultFramebufferObject`, `devicePixelRatioF`). Грузится в рантайме:
сначала рядом с исполняемым файлом, затем по системным путям.
## Сборка вспомогательной библиотеки (csrc/)
| Где собираем | Команда | Результат |
|---|---|---|
| Linux | `make -C csrc` | `libqlclglwidget.so` |
| macOS | `make -C csrc` (авто) или `make -C csrc macos` | `libqlclglwidget.dylib` |
| Linux → Windows (кросс) | `make -C csrc windows` | `qlclglwidget.dll` (MinGW) |
| Windows, MSYS2 MinGW64 shell | `make -C csrc` (авто) или `make -C csrc windows-native` | `qlclglwidget.dll` (MinGW) |
| Windows, Qt MinGW-kit без pkg-config | `make -C csrc windows MINGW_CXX=g++ WIN_QT_INC=C:/Qt/6.x/mingw_64/include WIN_QT_LIB=C:/Qt/6.x/mingw_64/lib` | `qlclglwidget.dll` (MinGW) |
| Windows, MSVC | `csrc\build-msvc.bat` из «x64 Native Tools Command Prompt» с выставленным `QTDIR` | `qlclglwidget.dll` (MSVC) |
Плюс:
```
make -C csrc install # установить в /usr/local/lib (PREFIX/DESTDIR поддерживаются)
make -C csrc install-app APPDIR=/путь/к/бинарнику # положить рядом с приложением
```
Для кросс-сборки нужен тулчейн mingw-w64 и **MinGW-сборка Qt6** (AUR
`mingw-w64-qt6-base`, MXE, либо Qt MinGW-kit; пути переопределяются
`MINGW_PREFIX`/`WIN_QT_INC`/`WIN_QT_LIB`). Для MSYS2:
`pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-qt6-base pkgconf make`.
**ABI:** MinGW-DLL работает только с MinGW-сборкой Qt6 на целевой машине,
MSVC-DLL — только с MSVC-Qt (официальные бинарники Qt из online-инсталлятора —
MSVC). Выбирайте вариант под ту Qt6, с которой собрана libQt6Pas приложения.
## Использование
В проекте: зависимость `LazOpenGLContext``LazOpenGLContextEx`,
в uses: `OpenGLContext``OpenGLContextEx`.
```
make -C csrc
lazbuild --ws=qt6 lazopenglcontextex.lpk
make -C csrc install-app APPDIR=<каталог с бинарником приложения>
```
## Как устроен Qt-бэкенд
- Qt сам делает контекст текущим и биндит FBO виджета перед вызовом `paintGL()`;
оттуда доставляется `LM_PAINT`, так что весь рендер в `OnPaint` работает как раньше.
- `SwapBuffers` внутри paint — no-op (композитингом FBO занимается Qt после
возврата из `paintGL`); вне paint — планирует перерисовку (`QWidget::update`).
- `MakeCurrent`/`ReleaseContext` вне paint → `QOpenGLWidget::makeCurrent/doneCurrent`.
До первого показа виджета контекста ещё нет — `MakeCurrent` вернёт False.
- `LOpenGLViewport` (AutoResizeViewport) умножает координаты на devicePixelRatio.
## Ограничения / нюансы
- **Не вызывать `glBindFramebuffer(..., 0)`** — QOpenGLWidget рендерит в свой FBO.
- **Альфа фреймбуфера = прозрачность виджета.** Qt композитит FBO с учётом
альфы; легаси-GL-код после блендинга оставляет alpha<1, и виджет просвечивал
бы насквозь. Поэтому обёртка после каждого paintGL принудительно заливает
альфу единицей (`QLCLGLWidget_setForceOpaque`, включено по умолчанию).
Отключается автоматически, если контрол запросил `AlphaBits > 0` — тогда
альфа остаётся под контролем приложения.
- **SharedControl игнорируется**: Qt автоматически шарит контексты всех
QOpenGLWidget внутри одного top-level окна. Для шаринга между окнами нужно
выставить `Qt::AA_ShareOpenGLContexts` до создания QApplication.
- **Windows + qt6**: чтобы Qt не выбрал ANGLE/GLES (где нет immediate mode),
выставить `QT_OPENGL=desktop` или атрибут `AA_UseDesktopOpenGL`.
- **HiDPI (devicePixelRatio > 1)**: FBO больше логического размера виджета.
Явные вызовы `glViewport` в коде приложения должны умножать на dpr сами.
- AUXBuffers не поддерживаются QSurfaceFormat (игнорируются).
- Qt4 (LCLQT), gtk1 и carbon из форка выброшены.
## Статус проверки
- Linux Wayland (KDE, qt6): спектр EWSDR рендерится через GL, стартует без
ошибок, скриншот подтверждён (2026-07-03).
- Linux XWayland/xcb: стартует без ошибок.
- Windows/macOS: не проверялось (build.sh под них ещё нет — нужен аналог
с MSVC/clang и Qt-заголовками).